Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / web / WebFrameWidgetImpl.cpp
blob38c3a456bf01abbcc2db4850f374f9e18c4e374c
1 /*
2 * Copyright (C) 2014 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "config.h"
32 #include "web/WebFrameWidgetImpl.h"
34 #include "core/editing/EditingUtilities.h"
35 #include "core/editing/Editor.h"
36 #include "core/editing/FrameSelection.h"
37 #include "core/editing/InputMethodController.h"
38 #include "core/editing/PlainTextRange.h"
39 #include "core/frame/FrameView.h"
40 #include "core/frame/RemoteFrame.h"
41 #include "core/frame/Settings.h"
42 #include "core/input/EventHandler.h"
43 #include "core/layout/LayoutView.h"
44 #include "core/layout/compositing/DeprecatedPaintLayerCompositor.h"
45 #include "core/page/ContextMenuController.h"
46 #include "core/page/FocusController.h"
47 #include "core/page/Page.h"
48 #include "platform/KeyboardCodes.h"
49 #include "platform/NotImplemented.h"
50 #include "public/web/WebBeginFrameArgs.h"
51 #include "public/web/WebWidgetClient.h"
52 #include "web/ContextMenuAllowedScope.h"
53 #include "web/WebDevToolsAgentImpl.h"
54 #include "web/WebInputEventConversion.h"
55 #include "web/WebLocalFrameImpl.h"
56 #include "web/WebPluginContainerImpl.h"
57 #include "web/WebRemoteFrameImpl.h"
58 #include "web/WebViewFrameWidget.h"
60 namespace blink {
62 // WebFrameWidget ----------------------------------------------------------------
64 WebFrameWidget* WebFrameWidget::create(WebWidgetClient* client, WebLocalFrame* localRoot)
66 // Pass the WebFrameWidget's self-reference to the caller.
67 return WebFrameWidgetImpl::create(client, localRoot);
70 WebFrameWidget* WebFrameWidget::create(WebWidgetClient* client, WebView* webView, WebLocalFrame* mainFrame)
72 return new WebViewFrameWidget(client, toWebViewImpl(*webView), toWebLocalFrameImpl(*mainFrame));
75 WebFrameWidgetImpl* WebFrameWidgetImpl::create(WebWidgetClient* client, WebLocalFrame* localRoot)
77 // Pass the WebFrameWidgetImpl's self-reference to the caller.
78 #if ENABLE(OILPAN)
79 return new WebFrameWidgetImpl(client, localRoot); // SelfKeepAlive is set in constructor.
80 #else
81 return adoptRef(new WebFrameWidgetImpl(client, localRoot)).leakRef();
82 #endif
85 // static
86 HashSet<WebFrameWidgetImpl*>& WebFrameWidgetImpl::allInstances()
88 DEFINE_STATIC_LOCAL(HashSet<WebFrameWidgetImpl*>, allInstances, ());
89 return allInstances;
92 WebFrameWidgetImpl::WebFrameWidgetImpl(WebWidgetClient* client, WebLocalFrame* localRoot)
93 : m_client(client)
94 , m_localRoot(toWebLocalFrameImpl(localRoot))
95 , m_layerTreeView(nullptr)
96 , m_rootLayer(nullptr)
97 , m_rootGraphicsLayer(nullptr)
98 , m_isAcceleratedCompositingActive(false)
99 , m_layerTreeViewClosed(false)
100 , m_suppressNextKeypressEvent(false)
101 , m_ignoreInputEvents(false)
102 #if ENABLE(OILPAN)
103 , m_selfKeepAlive(this)
104 #endif
106 ASSERT(m_localRoot->frame()->isLocalRoot());
107 initializeLayerTreeView();
108 m_localRoot->setFrameWidget(this);
109 allInstances().add(this);
112 WebFrameWidgetImpl::~WebFrameWidgetImpl()
116 DEFINE_TRACE(WebFrameWidgetImpl)
118 visitor->trace(m_localRoot);
119 visitor->trace(m_mouseCaptureNode);
122 // WebWidget ------------------------------------------------------------------
124 void WebFrameWidgetImpl::close()
126 WebDevToolsAgentImpl::webFrameWidgetImplClosed(this);
127 ASSERT(allInstances().contains(this));
128 allInstances().remove(this);
130 m_localRoot->setFrameWidget(nullptr);
131 m_localRoot = nullptr;
132 // Reset the delegate to prevent notifications being sent as we're being
133 // deleted.
134 m_client = nullptr;
136 m_layerTreeView = nullptr;
137 m_rootLayer = nullptr;
138 m_rootGraphicsLayer = nullptr;
140 #if ENABLE(OILPAN)
141 m_selfKeepAlive.clear();
142 #else
143 deref(); // Balances ref() acquired in WebFrameWidget::create
144 #endif
147 WebSize WebFrameWidgetImpl::size()
149 return m_size;
152 void WebFrameWidgetImpl::willStartLiveResize()
154 if (m_localRoot->frameView())
155 m_localRoot->frameView()->willStartLiveResize();
158 void WebFrameWidgetImpl::resize(const WebSize& newSize)
160 if (m_size == newSize)
161 return;
163 FrameView* view = m_localRoot->frameView();
164 if (!view)
165 return;
167 m_size = newSize;
169 updateMainFrameLayoutSize();
171 view->resize(m_size);
173 // FIXME: In WebViewImpl this layout was a precursor to setting the minimum scale limit.
174 // It is not clear if this is necessary for frame-level widget resize.
175 if (view->needsLayout())
176 view->layout();
178 // FIXME: Investigate whether this is needed; comment from eseidel suggests that this function
179 // is flawed.
180 sendResizeEventAndRepaint();
183 void WebFrameWidgetImpl::sendResizeEventAndRepaint()
185 // FIXME: This is wrong. The FrameView is responsible sending a resizeEvent
186 // as part of layout. Layout is also responsible for sending invalidations
187 // to the embedder. This method and all callers may be wrong. -- eseidel.
188 if (m_localRoot->frameView()) {
189 // Enqueues the resize event.
190 m_localRoot->frame()->document()->enqueueResizeEvent();
193 if (m_client) {
194 if (isAcceleratedCompositingActive()) {
195 updateLayerTreeViewport();
196 } else {
197 WebRect damagedRect(0, 0, m_size.width, m_size.height);
198 m_client->didInvalidateRect(damagedRect);
203 void WebFrameWidgetImpl::resizePinchViewport(const WebSize& newSize)
205 // TODO(bokan): To Remove.
208 void WebFrameWidgetImpl::resizeVisualViewport(const WebSize& newSize)
210 // FIXME: Implement visual viewport for out-of-process iframes.
213 void WebFrameWidgetImpl::updateMainFrameLayoutSize()
215 if (!m_localRoot)
216 return;
218 RefPtrWillBeRawPtr<FrameView> view = m_localRoot->frameView();
219 if (!view)
220 return;
222 WebSize layoutSize = m_size;
224 view->setLayoutSize(layoutSize);
227 void WebFrameWidgetImpl::setIgnoreInputEvents(bool newValue)
229 ASSERT(m_ignoreInputEvents != newValue);
230 m_ignoreInputEvents = newValue;
233 void WebFrameWidgetImpl::willEndLiveResize()
235 if (m_localRoot->frameView())
236 m_localRoot->frameView()->willEndLiveResize();
239 void WebFrameWidgetImpl::didEnterFullScreen()
241 // FIXME: Implement full screen for out-of-process iframes.
244 void WebFrameWidgetImpl::didExitFullScreen()
246 // FIXME: Implement full screen for out-of-process iframes.
249 void WebFrameWidgetImpl::beginFrame(const WebBeginFrameArgs& frameTime)
251 TRACE_EVENT0("blink", "WebFrameWidgetImpl::beginFrame");
253 WebBeginFrameArgs validFrameTime(frameTime);
254 if (!validFrameTime.lastFrameTimeMonotonic)
255 validFrameTime.lastFrameTimeMonotonic = monotonicallyIncreasingTime();
257 PageWidgetDelegate::animate(*page(), validFrameTime.lastFrameTimeMonotonic, *m_localRoot->frame());
260 void WebFrameWidgetImpl::layout()
262 TRACE_EVENT0("blink", "WebFrameWidgetImpl::layout");
263 if (!m_localRoot)
264 return;
266 PageWidgetDelegate::layout(*page(), *m_localRoot->frame());
267 updateLayerTreeBackgroundColor();
270 void WebFrameWidgetImpl::paint(WebCanvas* canvas, const WebRect& rect)
272 // Out-of-process iframes require compositing.
273 ASSERT_NOT_REACHED();
277 void WebFrameWidgetImpl::updateLayerTreeViewport()
279 if (!page() || !m_layerTreeView)
280 return;
282 // FIXME: We need access to page scale information from the WebView.
283 m_layerTreeView->setPageScaleFactorAndLimits(1, 1, 1);
286 void WebFrameWidgetImpl::updateLayerTreeBackgroundColor()
288 if (!m_layerTreeView)
289 return;
291 m_layerTreeView->setBackgroundColor(alphaChannel(view()->backgroundColorOverride()) ? view()->backgroundColorOverride() : view()->backgroundColor());
294 void WebFrameWidgetImpl::updateLayerTreeDeviceScaleFactor()
296 ASSERT(page());
297 ASSERT(m_layerTreeView);
299 float deviceScaleFactor = page()->deviceScaleFactor();
300 m_layerTreeView->setDeviceScaleFactor(deviceScaleFactor);
303 bool WebFrameWidgetImpl::isTransparent() const
305 // FIXME: This might need to proxy to the WebView's isTransparent().
306 return false;
309 void WebFrameWidgetImpl::layoutAndPaintAsync(WebLayoutAndPaintAsyncCallback* callback)
311 m_layerTreeView->layoutAndPaintAsync(callback);
314 void WebFrameWidgetImpl::compositeAndReadbackAsync(WebCompositeAndReadbackAsyncCallback* callback)
316 m_layerTreeView->compositeAndReadbackAsync(callback);
319 void WebFrameWidgetImpl::themeChanged()
321 FrameView* view = m_localRoot->frameView();
323 WebRect damagedRect(0, 0, m_size.width, m_size.height);
324 view->invalidateRect(damagedRect);
327 const WebInputEvent* WebFrameWidgetImpl::m_currentInputEvent = nullptr;
329 // FIXME: autogenerate this kind of code, and use it throughout Blink rather than
330 // the one-offs for subsets of these values.
331 static String inputTypeToName(WebInputEvent::Type type)
333 switch (type) {
334 case WebInputEvent::MouseDown:
335 return EventTypeNames::mousedown;
336 case WebInputEvent::MouseUp:
337 return EventTypeNames::mouseup;
338 case WebInputEvent::MouseMove:
339 return EventTypeNames::mousemove;
340 case WebInputEvent::MouseEnter:
341 return EventTypeNames::mouseenter;
342 case WebInputEvent::MouseLeave:
343 return EventTypeNames::mouseleave;
344 case WebInputEvent::ContextMenu:
345 return EventTypeNames::contextmenu;
346 case WebInputEvent::MouseWheel:
347 return EventTypeNames::mousewheel;
348 case WebInputEvent::KeyDown:
349 return EventTypeNames::keydown;
350 case WebInputEvent::KeyUp:
351 return EventTypeNames::keyup;
352 case WebInputEvent::GestureScrollBegin:
353 return EventTypeNames::gesturescrollstart;
354 case WebInputEvent::GestureScrollEnd:
355 return EventTypeNames::gesturescrollend;
356 case WebInputEvent::GestureScrollUpdate:
357 return EventTypeNames::gesturescrollupdate;
358 case WebInputEvent::GestureTapDown:
359 return EventTypeNames::gesturetapdown;
360 case WebInputEvent::GestureShowPress:
361 return EventTypeNames::gestureshowpress;
362 case WebInputEvent::GestureTap:
363 return EventTypeNames::gesturetap;
364 case WebInputEvent::GestureTapUnconfirmed:
365 return EventTypeNames::gesturetapunconfirmed;
366 case WebInputEvent::TouchStart:
367 return EventTypeNames::touchstart;
368 case WebInputEvent::TouchMove:
369 return EventTypeNames::touchmove;
370 case WebInputEvent::TouchEnd:
371 return EventTypeNames::touchend;
372 case WebInputEvent::TouchCancel:
373 return EventTypeNames::touchcancel;
374 default:
375 return String("unknown");
379 bool WebFrameWidgetImpl::handleInputEvent(const WebInputEvent& inputEvent)
382 TRACE_EVENT1("input", "WebFrameWidgetImpl::handleInputEvent", "type", inputTypeToName(inputEvent.type).ascii());
384 // Report the event to be NOT processed by WebKit, so that the browser can handle it appropriately.
385 if (m_ignoreInputEvents)
386 return false;
388 // FIXME: pass event to m_localRoot's WebDevToolsAgentImpl once available.
390 TemporaryChange<const WebInputEvent*> currentEventChange(m_currentInputEvent, &inputEvent);
392 if (m_mouseCaptureNode && WebInputEvent::isMouseEventType(inputEvent.type)) {
393 TRACE_EVENT1("input", "captured mouse event", "type", inputEvent.type);
394 // Save m_mouseCaptureNode since mouseCaptureLost() will clear it.
395 RefPtrWillBeRawPtr<Node> node = m_mouseCaptureNode;
397 // Not all platforms call mouseCaptureLost() directly.
398 if (inputEvent.type == WebInputEvent::MouseUp)
399 mouseCaptureLost();
401 OwnPtr<UserGestureIndicator> gestureIndicator;
403 AtomicString eventType;
404 switch (inputEvent.type) {
405 case WebInputEvent::MouseMove:
406 eventType = EventTypeNames::mousemove;
407 break;
408 case WebInputEvent::MouseLeave:
409 eventType = EventTypeNames::mouseout;
410 break;
411 case WebInputEvent::MouseDown:
412 eventType = EventTypeNames::mousedown;
413 gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProcessingNewUserGesture));
414 m_mouseCaptureGestureToken = gestureIndicator->currentToken();
415 break;
416 case WebInputEvent::MouseUp:
417 eventType = EventTypeNames::mouseup;
418 gestureIndicator = adoptPtr(new UserGestureIndicator(m_mouseCaptureGestureToken.release()));
419 break;
420 default:
421 ASSERT_NOT_REACHED();
424 node->dispatchMouseEvent(
425 PlatformMouseEventBuilder(m_localRoot->frameView(), static_cast<const WebMouseEvent&>(inputEvent)),
426 eventType, static_cast<const WebMouseEvent&>(inputEvent).clickCount);
427 return true;
430 return PageWidgetDelegate::handleInputEvent(*this, inputEvent, m_localRoot->frame());
433 void WebFrameWidgetImpl::setCursorVisibilityState(bool isVisible)
435 page()->setIsCursorVisible(isVisible);
438 bool WebFrameWidgetImpl::hasTouchEventHandlersAt(const WebPoint& point)
440 // FIXME: Implement this. Note that the point must be divided by pageScaleFactor.
441 return true;
444 void WebFrameWidgetImpl::scheduleAnimation()
446 if (m_layerTreeView) {
447 m_layerTreeView->setNeedsBeginFrame();
448 return;
450 if (m_client)
451 m_client->scheduleAnimation();
454 void WebFrameWidgetImpl::applyViewportDeltas(
455 const WebFloatSize& visualViewportDelta,
456 const WebFloatSize& mainFrameDelta,
457 const WebFloatSize& elasticOverscrollDelta,
458 float pageScaleDelta,
459 float topControlsDelta)
461 // FIXME: To be implemented.
464 void WebFrameWidgetImpl::mouseCaptureLost()
466 TRACE_EVENT_ASYNC_END0("input", "capturing mouse", this);
467 m_mouseCaptureNode = nullptr;
470 void WebFrameWidgetImpl::setFocus(bool enable)
472 page()->focusController().setFocused(enable);
473 if (enable) {
474 page()->focusController().setActive(true);
475 RefPtrWillBeRawPtr<Frame> focusedFrame = page()->focusController().focusedFrame();
476 if (focusedFrame && focusedFrame->isLocalFrame()) {
477 LocalFrame* localFrame = toLocalFrame(focusedFrame.get());
478 Element* element = localFrame->document()->focusedElement();
479 if (element && localFrame->selection().selection().isNone()) {
480 // If the selection was cleared while the WebView was not
481 // focused, then the focus element shows with a focus ring but
482 // no caret and does respond to keyboard inputs.
483 if (element->isTextFormControl()) {
484 element->updateFocusAppearance(true);
485 } else if (element->isContentEditable()) {
486 // updateFocusAppearance() selects all the text of
487 // contentseditable DIVs. So we set the selection explicitly
488 // instead. Note that this has the side effect of moving the
489 // caret back to the beginning of the text.
490 Position position(element, 0);
491 localFrame->selection().setSelection(VisibleSelection(position, SEL_DEFAULT_AFFINITY));
498 bool WebFrameWidgetImpl::setComposition(
499 const WebString& text,
500 const WebVector<WebCompositionUnderline>& underlines,
501 int selectionStart,
502 int selectionEnd)
504 // FIXME: To be implemented.
505 return false;
508 bool WebFrameWidgetImpl::confirmComposition()
510 // FIXME: To be implemented.
511 return false;
514 bool WebFrameWidgetImpl::confirmComposition(ConfirmCompositionBehavior selectionBehavior)
516 // FIXME: To be implemented.
517 return false;
520 bool WebFrameWidgetImpl::confirmComposition(const WebString& text)
522 // FIXME: To be implemented.
523 return false;
526 bool WebFrameWidgetImpl::compositionRange(size_t* location, size_t* length)
528 // FIXME: To be implemented.
529 return false;
532 WebTextInputInfo WebFrameWidgetImpl::textInputInfo()
534 return view()->textInputInfo();
537 WebColor WebFrameWidgetImpl::backgroundColor() const
539 if (isTransparent())
540 return Color::transparent;
541 if (!m_localRoot->frameView())
542 return view()->backgroundColor();
543 FrameView* view = m_localRoot->frameView();
544 return view->documentBackgroundColor().rgb();
547 bool WebFrameWidgetImpl::selectionBounds(WebRect& anchor, WebRect& focus) const
549 const Frame* frame = focusedCoreFrame();
550 if (!frame || !frame->isLocalFrame())
551 return false;
553 const LocalFrame* localFrame = toLocalFrame(frame);
554 if (!localFrame)
555 return false;
556 FrameSelection& selection = localFrame->selection();
558 if (selection.isCaret()) {
559 anchor = focus = selection.absoluteCaretBounds();
560 } else {
561 const EphemeralRange selectedRange = selection.selection().toNormalizedEphemeralRange();
562 if (selectedRange.isNull())
563 return false;
564 anchor = localFrame->editor().firstRectForRange(EphemeralRange(selectedRange.startPosition()));
565 focus = localFrame->editor().firstRectForRange(EphemeralRange(selectedRange.endPosition()));
568 // FIXME: This doesn't apply page scale. This should probably be contents to viewport. crbug.com/459293.
569 IntRect scaledAnchor(localFrame->view()->contentsToRootFrame(anchor));
570 IntRect scaledFocus(localFrame->view()->contentsToRootFrame(focus));
572 anchor = scaledAnchor;
573 focus = scaledFocus;
575 if (!selection.selection().isBaseFirst())
576 std::swap(anchor, focus);
577 return true;
580 bool WebFrameWidgetImpl::selectionTextDirection(WebTextDirection& start, WebTextDirection& end) const
582 if (!focusedCoreFrame()->isLocalFrame())
583 return false;
584 const LocalFrame* frame = toLocalFrame(focusedCoreFrame());
585 if (!frame)
586 return false;
587 FrameSelection& selection = frame->selection();
588 if (selection.selection().toNormalizedEphemeralRange().isNull())
589 return false;
590 start = toWebTextDirection(primaryDirectionOf(*selection.start().anchorNode()));
591 end = toWebTextDirection(primaryDirectionOf(*selection.end().anchorNode()));
592 return true;
595 bool WebFrameWidgetImpl::isSelectionAnchorFirst() const
597 if (!focusedCoreFrame()->isLocalFrame())
598 return false;
599 if (const LocalFrame* frame = toLocalFrame(focusedCoreFrame()))
600 return frame->selection().selection().isBaseFirst();
601 return false;
604 bool WebFrameWidgetImpl::caretOrSelectionRange(size_t* location, size_t* length)
606 if (!focusedCoreFrame()->isLocalFrame())
607 return false;
608 const LocalFrame* focused = toLocalFrame(focusedCoreFrame());
609 if (!focused)
610 return false;
612 PlainTextRange selectionOffsets = focused->inputMethodController().getSelectionOffsets();
613 if (selectionOffsets.isNull())
614 return false;
616 *location = selectionOffsets.start();
617 *length = selectionOffsets.length();
618 return true;
621 void WebFrameWidgetImpl::setTextDirection(WebTextDirection direction)
623 // The Editor::setBaseWritingDirection() function checks if we can change
624 // the text direction of the selected node and updates its DOM "dir"
625 // attribute and its CSS "direction" property.
626 // So, we just call the function as Safari does.
627 if (!focusedCoreFrame()->isLocalFrame())
628 return;
629 const LocalFrame* focused = toLocalFrame(focusedCoreFrame());
630 if (!focused)
631 return;
633 Editor& editor = focused->editor();
634 if (!editor.canEdit())
635 return;
637 switch (direction) {
638 case WebTextDirectionDefault:
639 editor.setBaseWritingDirection(NaturalWritingDirection);
640 break;
642 case WebTextDirectionLeftToRight:
643 editor.setBaseWritingDirection(LeftToRightWritingDirection);
644 break;
646 case WebTextDirectionRightToLeft:
647 editor.setBaseWritingDirection(RightToLeftWritingDirection);
648 break;
650 default:
651 notImplemented();
652 break;
656 bool WebFrameWidgetImpl::isAcceleratedCompositingActive() const
658 return m_isAcceleratedCompositingActive;
661 void WebFrameWidgetImpl::willCloseLayerTreeView()
663 setIsAcceleratedCompositingActive(false);
664 m_layerTreeView = nullptr;
665 m_layerTreeViewClosed = true;
668 void WebFrameWidgetImpl::didChangeWindowResizerRect()
670 if (m_localRoot->frameView())
671 m_localRoot->frameView()->windowResizerRectChanged();
674 void WebFrameWidgetImpl::handleMouseLeave(LocalFrame& mainFrame, const WebMouseEvent& event)
676 // FIXME: WebWidget doesn't have the method below.
677 // m_client->setMouseOverURL(WebURL());
678 PageWidgetEventHandler::handleMouseLeave(mainFrame, event);
681 void WebFrameWidgetImpl::handleMouseDown(LocalFrame& mainFrame, const WebMouseEvent& event)
683 // Take capture on a mouse down on a plugin so we can send it mouse events.
684 // If the hit node is a plugin but a scrollbar is over it don't start mouse
685 // capture because it will interfere with the scrollbar receiving events.
686 IntPoint point(event.x, event.y);
687 if (event.button == WebMouseEvent::ButtonLeft) {
688 point = m_localRoot->frameView()->rootFrameToContents(point);
689 HitTestResult result(m_localRoot->frame()->eventHandler().hitTestResultAtPoint(point));
690 result.setToShadowHostIfInUserAgentShadowRoot();
691 Node* hitNode = result.innerNode();
693 if (!result.scrollbar() && hitNode && hitNode->layoutObject() && hitNode->layoutObject()->isEmbeddedObject()) {
694 m_mouseCaptureNode = hitNode;
695 TRACE_EVENT_ASYNC_BEGIN0("input", "capturing mouse", this);
699 PageWidgetEventHandler::handleMouseDown(mainFrame, event);
701 if (event.button == WebMouseEvent::ButtonLeft && m_mouseCaptureNode)
702 m_mouseCaptureGestureToken = mainFrame.eventHandler().takeLastMouseDownGestureToken();
704 // Dispatch the contextmenu event regardless of if the click was swallowed.
705 if (!page()->settings().showContextMenuOnMouseUp()) {
706 #if OS(MACOSX)
707 if (event.button == WebMouseEvent::ButtonRight || (event.button == WebMouseEvent::ButtonLeft && event.modifiers & WebMouseEvent::ControlKey))
708 mouseContextMenu(event);
709 #else
710 if (event.button == WebMouseEvent::ButtonRight)
711 mouseContextMenu(event);
712 #endif
716 void WebFrameWidgetImpl::mouseContextMenu(const WebMouseEvent& event)
718 page()->contextMenuController().clearContextMenu();
720 PlatformMouseEventBuilder pme(m_localRoot->frameView(), event);
722 // Find the right target frame. See issue 1186900.
723 HitTestResult result = hitTestResultForRootFramePos(pme.position());
724 Frame* targetFrame;
725 if (result.innerNodeOrImageMapImage())
726 targetFrame = result.innerNodeOrImageMapImage()->document().frame();
727 else
728 targetFrame = page()->focusController().focusedOrMainFrame();
730 // This will need to be changed to a nullptr check when focus control
731 // is refactored, at which point focusedOrMainFrame will never return a
732 // RemoteFrame.
733 // See https://crbug.com/341918.
734 if (!targetFrame->isLocalFrame())
735 return;
737 LocalFrame* targetLocalFrame = toLocalFrame(targetFrame);
739 #if OS(WIN)
740 targetLocalFrame->view()->setCursor(pointerCursor());
741 #endif
744 ContextMenuAllowedScope scope;
745 targetLocalFrame->eventHandler().sendContextMenuEvent(pme, nullptr);
747 // Actually showing the context menu is handled by the ContextMenuClient
748 // implementation...
751 void WebFrameWidgetImpl::handleMouseUp(LocalFrame& mainFrame, const WebMouseEvent& event)
753 PageWidgetEventHandler::handleMouseUp(mainFrame, event);
755 if (page()->settings().showContextMenuOnMouseUp()) {
756 // Dispatch the contextmenu event regardless of if the click was swallowed.
757 // On Mac/Linux, we handle it on mouse down, not up.
758 if (event.button == WebMouseEvent::ButtonRight)
759 mouseContextMenu(event);
763 bool WebFrameWidgetImpl::handleMouseWheel(LocalFrame& mainFrame, const WebMouseWheelEvent& event)
765 return PageWidgetEventHandler::handleMouseWheel(mainFrame, event);
768 bool WebFrameWidgetImpl::handleGestureEvent(const WebGestureEvent& event)
770 bool eventSwallowed = false;
771 bool eventCancelled = false;
772 switch (event.type) {
773 case WebInputEvent::GestureScrollBegin:
774 case WebInputEvent::GestureScrollEnd:
775 case WebInputEvent::GestureScrollUpdate:
776 case WebInputEvent::GestureTap:
777 case WebInputEvent::GestureTapUnconfirmed:
778 case WebInputEvent::GestureTapDown:
779 case WebInputEvent::GestureShowPress:
780 case WebInputEvent::GestureTapCancel:
781 case WebInputEvent::GestureDoubleTap:
782 case WebInputEvent::GestureTwoFingerTap:
783 case WebInputEvent::GestureLongPress:
784 case WebInputEvent::GestureLongTap:
785 break;
786 case WebInputEvent::GestureFlingStart:
787 case WebInputEvent::GestureFlingCancel:
788 m_client->didHandleGestureEvent(event, eventCancelled);
789 return false;
790 default:
791 ASSERT_NOT_REACHED();
793 LocalFrame* frame = m_localRoot->frame();
794 eventSwallowed = frame->eventHandler().handleGestureEvent(PlatformGestureEventBuilder(frame->view(), event));
795 m_client->didHandleGestureEvent(event, eventCancelled);
796 return eventSwallowed;
799 bool WebFrameWidgetImpl::handleKeyEvent(const WebKeyboardEvent& event)
801 ASSERT((event.type == WebInputEvent::RawKeyDown)
802 || (event.type == WebInputEvent::KeyDown)
803 || (event.type == WebInputEvent::KeyUp));
805 // Please refer to the comments explaining the m_suppressNextKeypressEvent
806 // member.
807 // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
808 // Webkit. A keyDown event is typically associated with a keyPress(char)
809 // event and a keyUp event. We reset this flag here as this is a new keyDown
810 // event.
811 m_suppressNextKeypressEvent = false;
813 RefPtrWillBeRawPtr<Frame> focusedFrame = focusedCoreFrame();
814 if (focusedFrame && focusedFrame->isRemoteFrame()) {
815 WebRemoteFrameImpl* webFrame = WebRemoteFrameImpl::fromFrame(*toRemoteFrame(focusedFrame.get()));
816 webFrame->client()->forwardInputEvent(&event);
817 return true;
820 if (!focusedFrame || !focusedFrame->isLocalFrame())
821 return false;
823 RefPtrWillBeRawPtr<LocalFrame> frame = toLocalFrame(focusedFrame.get());
825 PlatformKeyboardEventBuilder evt(event);
827 if (frame->eventHandler().keyEvent(evt)) {
828 if (WebInputEvent::RawKeyDown == event.type) {
829 // Suppress the next keypress event unless the focused node is a plugin node.
830 // (Flash needs these keypress events to handle non-US keyboards.)
831 Element* element = focusedElement();
832 if (!element || !element->layoutObject() || !element->layoutObject()->isEmbeddedObject())
833 m_suppressNextKeypressEvent = true;
835 return true;
838 #if !OS(MACOSX)
839 const WebInputEvent::Type contextMenuTriggeringEventType =
840 #if OS(WIN)
841 WebInputEvent::KeyUp;
842 #else
843 WebInputEvent::RawKeyDown;
844 #endif
846 bool isUnmodifiedMenuKey = !(event.modifiers & WebInputEvent::InputModifiers) && event.windowsKeyCode == VKEY_APPS;
847 bool isShiftF10 = event.modifiers == WebInputEvent::ShiftKey && event.windowsKeyCode == VKEY_F10;
848 if ((isUnmodifiedMenuKey || isShiftF10) && event.type == contextMenuTriggeringEventType) {
849 view()->sendContextMenuEvent(event);
850 return true;
852 #endif // !OS(MACOSX)
854 return keyEventDefault(event);
857 bool WebFrameWidgetImpl::handleCharEvent(const WebKeyboardEvent& event)
859 ASSERT(event.type == WebInputEvent::Char);
861 // Please refer to the comments explaining the m_suppressNextKeypressEvent
862 // member. The m_suppressNextKeypressEvent is set if the KeyDown is
863 // handled by Webkit. A keyDown event is typically associated with a
864 // keyPress(char) event and a keyUp event. We reset this flag here as it
865 // only applies to the current keyPress event.
866 bool suppress = m_suppressNextKeypressEvent;
867 m_suppressNextKeypressEvent = false;
869 LocalFrame* frame = toLocalFrame(focusedCoreFrame());
870 if (!frame)
871 return suppress;
873 EventHandler& handler = frame->eventHandler();
875 PlatformKeyboardEventBuilder evt(event);
876 if (!evt.isCharacterKey())
877 return true;
879 // Accesskeys are triggered by char events and can't be suppressed.
880 if (handler.handleAccessKey(evt))
881 return true;
883 // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
884 // the eventHandler::keyEvent. We mimic this behavior on all platforms since
885 // for now we are converting other platform's key events to windows key
886 // events.
887 if (evt.isSystemKey())
888 return false;
890 if (!suppress && !handler.keyEvent(evt))
891 return keyEventDefault(event);
893 return true;
897 bool WebFrameWidgetImpl::keyEventDefault(const WebKeyboardEvent& event)
899 LocalFrame* frame = toLocalFrame(focusedCoreFrame());
900 if (!frame)
901 return false;
903 switch (event.type) {
904 case WebInputEvent::Char:
905 if (event.windowsKeyCode == VKEY_SPACE) {
906 int keyCode = ((event.modifiers & WebInputEvent::ShiftKey) ? VKEY_PRIOR : VKEY_NEXT);
907 return scrollViewWithKeyboard(keyCode, event.modifiers);
909 break;
910 case WebInputEvent::RawKeyDown:
911 if (event.modifiers == WebInputEvent::ControlKey) {
912 switch (event.windowsKeyCode) {
913 #if !OS(MACOSX)
914 case 'A':
915 WebFrame::fromFrame(focusedCoreFrame())->executeCommand(WebString::fromUTF8("SelectAll"));
916 return true;
917 case VKEY_INSERT:
918 case 'C':
919 WebFrame::fromFrame(focusedCoreFrame())->executeCommand(WebString::fromUTF8("Copy"));
920 return true;
921 #endif
922 // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl
923 // key combinations which affect scrolling. Safari is buggy in the
924 // sense that it scrolls the page for all Ctrl+scrolling key
925 // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
926 case VKEY_HOME:
927 case VKEY_END:
928 break;
929 default:
930 return false;
933 if (!event.isSystemKey && !(event.modifiers & WebInputEvent::ShiftKey))
934 return scrollViewWithKeyboard(event.windowsKeyCode, event.modifiers);
935 break;
936 default:
937 break;
939 return false;
942 bool WebFrameWidgetImpl::scrollViewWithKeyboard(int keyCode, int modifiers)
944 ScrollDirection scrollDirection;
945 ScrollGranularity scrollGranularity;
946 #if OS(MACOSX)
947 // Control-Up/Down should be PageUp/Down on Mac.
948 if (modifiers & WebMouseEvent::ControlKey) {
949 if (keyCode == VKEY_UP)
950 keyCode = VKEY_PRIOR;
951 else if (keyCode == VKEY_DOWN)
952 keyCode = VKEY_NEXT;
954 #endif
955 if (!mapKeyCodeForScroll(keyCode, &scrollDirection, &scrollGranularity))
956 return false;
958 if (LocalFrame* frame = toLocalFrame(focusedCoreFrame()))
959 return frame->eventHandler().bubblingScroll(scrollDirection, scrollGranularity);
960 return false;
963 bool WebFrameWidgetImpl::mapKeyCodeForScroll(
964 int keyCode,
965 ScrollDirection* scrollDirection,
966 ScrollGranularity* scrollGranularity)
968 switch (keyCode) {
969 case VKEY_LEFT:
970 *scrollDirection = ScrollLeftIgnoringWritingMode;
971 *scrollGranularity = ScrollByLine;
972 break;
973 case VKEY_RIGHT:
974 *scrollDirection = ScrollRightIgnoringWritingMode;
975 *scrollGranularity = ScrollByLine;
976 break;
977 case VKEY_UP:
978 *scrollDirection = ScrollUpIgnoringWritingMode;
979 *scrollGranularity = ScrollByLine;
980 break;
981 case VKEY_DOWN:
982 *scrollDirection = ScrollDownIgnoringWritingMode;
983 *scrollGranularity = ScrollByLine;
984 break;
985 case VKEY_HOME:
986 *scrollDirection = ScrollUpIgnoringWritingMode;
987 *scrollGranularity = ScrollByDocument;
988 break;
989 case VKEY_END:
990 *scrollDirection = ScrollDownIgnoringWritingMode;
991 *scrollGranularity = ScrollByDocument;
992 break;
993 case VKEY_PRIOR: // page up
994 *scrollDirection = ScrollUpIgnoringWritingMode;
995 *scrollGranularity = ScrollByPage;
996 break;
997 case VKEY_NEXT: // page down
998 *scrollDirection = ScrollDownIgnoringWritingMode;
999 *scrollGranularity = ScrollByPage;
1000 break;
1001 default:
1002 return false;
1005 return true;
1008 Frame* WebFrameWidgetImpl::focusedCoreFrame() const
1010 return page() ? page()->focusController().focusedOrMainFrame() : nullptr;
1013 Element* WebFrameWidgetImpl::focusedElement() const
1015 Frame* frame = page()->focusController().focusedFrame();
1016 if (!frame || !frame->isLocalFrame())
1017 return nullptr;
1019 Document* document = toLocalFrame(frame)->document();
1020 if (!document)
1021 return nullptr;
1023 return document->focusedElement();
1026 void WebFrameWidgetImpl::initializeLayerTreeView()
1028 if (m_client) {
1029 m_client->initializeLayerTreeView();
1030 m_layerTreeView = m_client->layerTreeView();
1033 if (WebDevToolsAgentImpl* devTools = m_localRoot->devToolsAgentImpl())
1034 devTools->layerTreeViewChanged(m_layerTreeView);
1036 page()->settings().setAcceleratedCompositingEnabled(m_layerTreeView);
1038 // FIXME: only unittests, click to play, Android priting, and printing (for headers and footers)
1039 // make this assert necessary. We should make them not hit this code and then delete allowsBrokenNullLayerTreeView.
1040 ASSERT(m_layerTreeView || !m_client || m_client->allowsBrokenNullLayerTreeView());
1043 void WebFrameWidgetImpl::setIsAcceleratedCompositingActive(bool active)
1045 // In the middle of shutting down; don't try to spin back up a compositor.
1046 // FIXME: compositing startup/shutdown should be refactored so that it
1047 // turns on explicitly rather than lazily, which causes this awkwardness.
1048 if (m_layerTreeViewClosed)
1049 return;
1051 ASSERT(!active || m_layerTreeView);
1053 if (m_isAcceleratedCompositingActive == active)
1054 return;
1056 if (!m_client)
1057 return;
1059 if (active) {
1060 TRACE_EVENT0("blink", "WebViewImpl::setIsAcceleratedCompositingActive(true)");
1061 m_layerTreeView->setRootLayer(*m_rootLayer);
1063 bool visible = page()->visibilityState() == PageVisibilityStateVisible;
1064 m_layerTreeView->setVisible(visible);
1065 updateLayerTreeDeviceScaleFactor();
1066 updateLayerTreeBackgroundColor();
1067 m_layerTreeView->setHasTransparentBackground(isTransparent());
1068 updateLayerTreeViewport();
1069 m_isAcceleratedCompositingActive = true;
1071 if (m_localRoot->frameView())
1072 m_localRoot->frameView()->setClipsRepaints(!m_isAcceleratedCompositingActive);
1075 DeprecatedPaintLayerCompositor* WebFrameWidgetImpl::compositor() const
1077 LocalFrame* frame = toLocalFrame(toCoreFrame(m_localRoot));
1078 if (!frame || !frame->document() || !frame->document()->layoutView())
1079 return nullptr;
1081 return frame->document()->layoutView()->compositor();
1084 void WebFrameWidgetImpl::setRootGraphicsLayer(GraphicsLayer* layer)
1086 m_rootGraphicsLayer = layer;
1087 m_rootLayer = layer ? layer->platformLayer() : nullptr;
1089 setIsAcceleratedCompositingActive(layer);
1091 if (m_layerTreeView) {
1092 if (m_rootLayer) {
1093 m_layerTreeView->setRootLayer(*m_rootLayer);
1094 // We register viewport layers here since there may not be a layer
1095 // tree view prior to this point.
1096 GraphicsLayer* rootScrollLayer = compositor()->scrollLayer();
1097 ASSERT(rootScrollLayer);
1098 WebLayer* pageScaleLayer = rootScrollLayer->parent() ? rootScrollLayer->parent()->platformLayer() : nullptr;
1099 m_layerTreeView->registerViewportLayers(nullptr, pageScaleLayer, rootScrollLayer->platformLayer(), nullptr);
1100 } else {
1101 m_layerTreeView->clearRootLayer();
1102 m_layerTreeView->clearViewportLayers();
1107 void WebFrameWidgetImpl::attachCompositorAnimationTimeline(WebCompositorAnimationTimeline* compositorTimeline)
1109 if (m_layerTreeView)
1110 m_layerTreeView->attachCompositorAnimationTimeline(compositorTimeline);
1114 void WebFrameWidgetImpl::detachCompositorAnimationTimeline(WebCompositorAnimationTimeline* compositorTimeline)
1116 if (m_layerTreeView)
1117 m_layerTreeView->detachCompositorAnimationTimeline(compositorTimeline);
1120 void WebFrameWidgetImpl::setVisibilityState(WebPageVisibilityState visibilityState, bool isInitialState)
1122 if (!page())
1123 return;
1125 // FIXME: This is not correct, since Show and Hide messages for a frame's Widget do not necessarily
1126 // correspond to Page visibility, but is necessary until we properly sort out OOPIF visibility.
1127 page()->setVisibilityState(static_cast<PageVisibilityState>(visibilityState), isInitialState);
1129 if (m_layerTreeView) {
1130 bool visible = visibilityState == WebPageVisibilityStateVisible;
1131 m_layerTreeView->setVisible(visible);
1135 HitTestResult WebFrameWidgetImpl::hitTestResultForRootFramePos(const IntPoint& posInRootFrame)
1137 IntPoint docPoint(m_localRoot->frame()->view()->rootFrameToContents(posInRootFrame));
1138 HitTestResult result = m_localRoot->frame()->eventHandler().hitTestResultAtPoint(docPoint, HitTestRequest::ReadOnly | HitTestRequest::Active);
1139 result.setToShadowHostIfInUserAgentShadowRoot();
1140 return result;
1143 } // namespace blink