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
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
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.
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"
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.
79 return new WebFrameWidgetImpl(client
, localRoot
); // SelfKeepAlive is set in constructor.
81 return adoptRef(new WebFrameWidgetImpl(client
, localRoot
)).leakRef();
86 HashSet
<WebFrameWidgetImpl
*>& WebFrameWidgetImpl::allInstances()
88 DEFINE_STATIC_LOCAL(HashSet
<WebFrameWidgetImpl
*>, allInstances
, ());
92 WebFrameWidgetImpl::WebFrameWidgetImpl(WebWidgetClient
* client
, WebLocalFrame
* localRoot
)
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)
103 , m_selfKeepAlive(this)
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
136 m_layerTreeView
= nullptr;
137 m_rootLayer
= nullptr;
138 m_rootGraphicsLayer
= nullptr;
141 m_selfKeepAlive
.clear();
143 deref(); // Balances ref() acquired in WebFrameWidget::create
147 WebSize
WebFrameWidgetImpl::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
)
163 FrameView
* view
= m_localRoot
->frameView();
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())
178 // FIXME: Investigate whether this is needed; comment from eseidel suggests that this function
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();
194 if (isAcceleratedCompositingActive()) {
195 updateLayerTreeViewport();
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()
218 RefPtrWillBeRawPtr
<FrameView
> view
= m_localRoot
->frameView();
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");
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
)
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
)
291 m_layerTreeView
->setBackgroundColor(alphaChannel(view()->backgroundColorOverride()) ? view()->backgroundColorOverride() : view()->backgroundColor());
294 void WebFrameWidgetImpl::updateLayerTreeDeviceScaleFactor()
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().
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
)
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
;
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
)
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
)
401 OwnPtr
<UserGestureIndicator
> gestureIndicator
;
403 AtomicString eventType
;
404 switch (inputEvent
.type
) {
405 case WebInputEvent::MouseMove
:
406 eventType
= EventTypeNames::mousemove
;
408 case WebInputEvent::MouseLeave
:
409 eventType
= EventTypeNames::mouseout
;
411 case WebInputEvent::MouseDown
:
412 eventType
= EventTypeNames::mousedown
;
413 gestureIndicator
= adoptPtr(new UserGestureIndicator(DefinitelyProcessingNewUserGesture
));
414 m_mouseCaptureGestureToken
= gestureIndicator
->currentToken();
416 case WebInputEvent::MouseUp
:
417 eventType
= EventTypeNames::mouseup
;
418 gestureIndicator
= adoptPtr(new UserGestureIndicator(m_mouseCaptureGestureToken
.release()));
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
);
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.
444 void WebFrameWidgetImpl::scheduleAnimation()
446 if (m_layerTreeView
) {
447 m_layerTreeView
->setNeedsBeginFrame();
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
);
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
,
504 // FIXME: To be implemented.
508 bool WebFrameWidgetImpl::confirmComposition()
510 // FIXME: To be implemented.
514 bool WebFrameWidgetImpl::confirmComposition(ConfirmCompositionBehavior selectionBehavior
)
516 // FIXME: To be implemented.
520 bool WebFrameWidgetImpl::confirmComposition(const WebString
& text
)
522 // FIXME: To be implemented.
526 bool WebFrameWidgetImpl::compositionRange(size_t* location
, size_t* length
)
528 // FIXME: To be implemented.
532 WebTextInputInfo
WebFrameWidgetImpl::textInputInfo()
534 return view()->textInputInfo();
537 WebColor
WebFrameWidgetImpl::backgroundColor() const
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())
553 const LocalFrame
* localFrame
= toLocalFrame(frame
);
556 FrameSelection
& selection
= localFrame
->selection();
558 if (selection
.isCaret()) {
559 anchor
= focus
= selection
.absoluteCaretBounds();
561 const EphemeralRange selectedRange
= selection
.selection().toNormalizedEphemeralRange();
562 if (selectedRange
.isNull())
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
;
575 if (!selection
.selection().isBaseFirst())
576 std::swap(anchor
, focus
);
580 bool WebFrameWidgetImpl::selectionTextDirection(WebTextDirection
& start
, WebTextDirection
& end
) const
582 if (!focusedCoreFrame()->isLocalFrame())
584 const LocalFrame
* frame
= toLocalFrame(focusedCoreFrame());
587 FrameSelection
& selection
= frame
->selection();
588 if (selection
.selection().toNormalizedEphemeralRange().isNull())
590 start
= toWebTextDirection(primaryDirectionOf(*selection
.start().anchorNode()));
591 end
= toWebTextDirection(primaryDirectionOf(*selection
.end().anchorNode()));
595 bool WebFrameWidgetImpl::isSelectionAnchorFirst() const
597 if (!focusedCoreFrame()->isLocalFrame())
599 if (const LocalFrame
* frame
= toLocalFrame(focusedCoreFrame()))
600 return frame
->selection().selection().isBaseFirst();
604 bool WebFrameWidgetImpl::caretOrSelectionRange(size_t* location
, size_t* length
)
606 if (!focusedCoreFrame()->isLocalFrame())
608 const LocalFrame
* focused
= toLocalFrame(focusedCoreFrame());
612 PlainTextRange selectionOffsets
= focused
->inputMethodController().getSelectionOffsets();
613 if (selectionOffsets
.isNull())
616 *location
= selectionOffsets
.start();
617 *length
= selectionOffsets
.length();
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())
629 const LocalFrame
* focused
= toLocalFrame(focusedCoreFrame());
633 Editor
& editor
= focused
->editor();
634 if (!editor
.canEdit())
638 case WebTextDirectionDefault
:
639 editor
.setBaseWritingDirection(NaturalWritingDirection
);
642 case WebTextDirectionLeftToRight
:
643 editor
.setBaseWritingDirection(LeftToRightWritingDirection
);
646 case WebTextDirectionRightToLeft
:
647 editor
.setBaseWritingDirection(RightToLeftWritingDirection
);
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()) {
707 if (event
.button
== WebMouseEvent::ButtonRight
|| (event
.button
== WebMouseEvent::ButtonLeft
&& event
.modifiers
& WebMouseEvent::ControlKey
))
708 mouseContextMenu(event
);
710 if (event
.button
== WebMouseEvent::ButtonRight
)
711 mouseContextMenu(event
);
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());
725 if (result
.innerNodeOrImageMapImage())
726 targetFrame
= result
.innerNodeOrImageMapImage()->document().frame();
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
733 // See https://crbug.com/341918.
734 if (!targetFrame
->isLocalFrame())
737 LocalFrame
* targetLocalFrame
= toLocalFrame(targetFrame
);
740 targetLocalFrame
->view()->setCursor(pointerCursor());
744 ContextMenuAllowedScope scope
;
745 targetLocalFrame
->eventHandler().sendContextMenuEvent(pme
, nullptr);
747 // Actually showing the context menu is handled by the ContextMenuClient
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
:
786 case WebInputEvent::GestureFlingStart
:
787 case WebInputEvent::GestureFlingCancel
:
788 m_client
->didHandleGestureEvent(event
, eventCancelled
);
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
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
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
);
820 if (!focusedFrame
|| !focusedFrame
->isLocalFrame())
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;
839 const WebInputEvent::Type contextMenuTriggeringEventType
=
841 WebInputEvent::KeyUp
;
843 WebInputEvent::RawKeyDown
;
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
);
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());
873 EventHandler
& handler
= frame
->eventHandler();
875 PlatformKeyboardEventBuilder
evt(event
);
876 if (!evt
.isCharacterKey())
879 // Accesskeys are triggered by char events and can't be suppressed.
880 if (handler
.handleAccessKey(evt
))
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
887 if (evt
.isSystemKey())
890 if (!suppress
&& !handler
.keyEvent(evt
))
891 return keyEventDefault(event
);
897 bool WebFrameWidgetImpl::keyEventDefault(const WebKeyboardEvent
& event
)
899 LocalFrame
* frame
= toLocalFrame(focusedCoreFrame());
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
);
910 case WebInputEvent::RawKeyDown
:
911 if (event
.modifiers
== WebInputEvent::ControlKey
) {
912 switch (event
.windowsKeyCode
) {
915 WebFrame::fromFrame(focusedCoreFrame())->executeCommand(WebString::fromUTF8("SelectAll"));
919 WebFrame::fromFrame(focusedCoreFrame())->executeCommand(WebString::fromUTF8("Copy"));
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.
933 if (!event
.isSystemKey
&& !(event
.modifiers
& WebInputEvent::ShiftKey
))
934 return scrollViewWithKeyboard(event
.windowsKeyCode
, event
.modifiers
);
942 bool WebFrameWidgetImpl::scrollViewWithKeyboard(int keyCode
, int modifiers
)
944 ScrollDirection scrollDirection
;
945 ScrollGranularity scrollGranularity
;
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
)
955 if (!mapKeyCodeForScroll(keyCode
, &scrollDirection
, &scrollGranularity
))
958 if (LocalFrame
* frame
= toLocalFrame(focusedCoreFrame()))
959 return frame
->eventHandler().bubblingScroll(scrollDirection
, scrollGranularity
);
963 bool WebFrameWidgetImpl::mapKeyCodeForScroll(
965 ScrollDirection
* scrollDirection
,
966 ScrollGranularity
* scrollGranularity
)
970 *scrollDirection
= ScrollLeftIgnoringWritingMode
;
971 *scrollGranularity
= ScrollByLine
;
974 *scrollDirection
= ScrollRightIgnoringWritingMode
;
975 *scrollGranularity
= ScrollByLine
;
978 *scrollDirection
= ScrollUpIgnoringWritingMode
;
979 *scrollGranularity
= ScrollByLine
;
982 *scrollDirection
= ScrollDownIgnoringWritingMode
;
983 *scrollGranularity
= ScrollByLine
;
986 *scrollDirection
= ScrollUpIgnoringWritingMode
;
987 *scrollGranularity
= ScrollByDocument
;
990 *scrollDirection
= ScrollDownIgnoringWritingMode
;
991 *scrollGranularity
= ScrollByDocument
;
993 case VKEY_PRIOR
: // page up
994 *scrollDirection
= ScrollUpIgnoringWritingMode
;
995 *scrollGranularity
= ScrollByPage
;
997 case VKEY_NEXT
: // page down
998 *scrollDirection
= ScrollDownIgnoringWritingMode
;
999 *scrollGranularity
= ScrollByPage
;
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())
1019 Document
* document
= toLocalFrame(frame
)->document();
1023 return document
->focusedElement();
1026 void WebFrameWidgetImpl::initializeLayerTreeView()
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
)
1051 ASSERT(!active
|| m_layerTreeView
);
1053 if (m_isAcceleratedCompositingActive
== 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())
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
) {
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);
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
)
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();
1143 } // namespace blink