2 * Copyright (C) 2011, 2012 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/WebViewImpl.h"
34 #include "core/CSSValueKeywords.h"
35 #include "core/HTMLNames.h"
36 #include "core/InputTypeNames.h"
37 #include "core/clipboard/DataObject.h"
38 #include "core/dom/Document.h"
39 #include "core/dom/Fullscreen.h"
40 #include "core/dom/LayoutTreeBuilderTraversal.h"
41 #include "core/dom/Text.h"
42 #include "core/editing/EditingUtilities.h"
43 #include "core/editing/Editor.h"
44 #include "core/editing/FrameSelection.h"
45 #include "core/editing/InputMethodController.h"
46 #include "core/editing/iterators/TextIterator.h"
47 #include "core/editing/markers/DocumentMarkerController.h"
48 #include "core/editing/serializers/HTMLInterchange.h"
49 #include "core/editing/serializers/Serialization.h"
50 #include "core/events/KeyboardEvent.h"
51 #include "core/events/UIEventWithKeyState.h"
52 #include "core/events/WheelEvent.h"
53 #include "core/fetch/UniqueIdentifier.h"
54 #include "core/frame/EventHandlerRegistry.h"
55 #include "core/frame/FrameHost.h"
56 #include "core/frame/FrameView.h"
57 #include "core/frame/LocalFrame.h"
58 #include "core/frame/PageScaleConstraintsSet.h"
59 #include "core/frame/RemoteFrame.h"
60 #include "core/frame/Settings.h"
61 #include "core/frame/SmartClip.h"
62 #include "core/frame/TopControls.h"
63 #include "core/frame/VisualViewport.h"
64 #include "core/html/HTMLInputElement.h"
65 #include "core/html/HTMLMediaElement.h"
66 #include "core/html/HTMLPlugInElement.h"
67 #include "core/html/HTMLTextAreaElement.h"
68 #include "core/input/EventHandler.h"
69 #include "core/input/TouchActionUtil.h"
70 #include "core/layout/LayoutPart.h"
71 #include "core/layout/LayoutView.h"
72 #include "core/layout/TextAutosizer.h"
73 #include "core/layout/compositing/DeprecatedPaintLayerCompositor.h"
74 #include "core/loader/DocumentLoader.h"
75 #include "core/loader/FrameLoadRequest.h"
76 #include "core/loader/FrameLoader.h"
77 #include "core/loader/FrameLoaderClient.h"
78 #include "core/loader/FrameLoaderStateMachine.h"
79 #include "core/page/ContextMenuController.h"
80 #include "core/page/ContextMenuProvider.h"
81 #include "core/page/DragController.h"
82 #include "core/page/DragData.h"
83 #include "core/page/DragSession.h"
84 #include "core/page/FocusController.h"
85 #include "core/page/FrameTree.h"
86 #include "core/page/Page.h"
87 #include "core/page/PagePopupClient.h"
88 #include "core/page/PointerLockController.h"
89 #include "core/page/ScopedPageLoadDeferrer.h"
90 #include "core/page/TouchDisambiguation.h"
91 #include "core/paint/DeprecatedPaintLayer.h"
92 #include "core/timing/DOMWindowPerformance.h"
93 #include "core/timing/Performance.h"
94 #include "modules/accessibility/AXObject.h"
95 #include "modules/accessibility/AXObjectCacheImpl.h"
96 #include "modules/credentialmanager/CredentialManagerClient.h"
97 #include "modules/encryptedmedia/MediaKeysController.h"
98 #include "modules/storage/StorageNamespaceController.h"
99 #include "modules/webgl/WebGLRenderingContext.h"
100 #include "platform/ContextMenu.h"
101 #include "platform/ContextMenuItem.h"
102 #include "platform/Cursor.h"
103 #include "platform/KeyboardCodes.h"
104 #include "platform/Logging.h"
105 #include "platform/NotImplemented.h"
106 #include "platform/PlatformGestureEvent.h"
107 #include "platform/PlatformKeyboardEvent.h"
108 #include "platform/PlatformMouseEvent.h"
109 #include "platform/PlatformWheelEvent.h"
110 #include "platform/RuntimeEnabledFeatures.h"
111 #include "platform/TraceEvent.h"
112 #include "platform/UserGestureIndicator.h"
113 #include "platform/exported/WebActiveGestureAnimation.h"
114 #include "platform/fonts/FontCache.h"
115 #include "platform/graphics/Color.h"
116 #include "platform/graphics/FirstPaintInvalidationTracking.h"
117 #include "platform/graphics/Image.h"
118 #include "platform/graphics/ImageBuffer.h"
119 #include "platform/graphics/gpu/DrawingBuffer.h"
120 #include "platform/scroll/ScrollbarTheme.h"
121 #include "platform/weborigin/SchemeRegistry.h"
122 #include "public/platform/Platform.h"
123 #include "public/platform/WebCompositeAndReadbackAsyncCallback.h"
124 #include "public/platform/WebCompositorSupport.h"
125 #include "public/platform/WebDragData.h"
126 #include "public/platform/WebFloatPoint.h"
127 #include "public/platform/WebGestureCurve.h"
128 #include "public/platform/WebImage.h"
129 #include "public/platform/WebLayerTreeView.h"
130 #include "public/platform/WebURLRequest.h"
131 #include "public/platform/WebVector.h"
132 #include "public/web/WebAXObject.h"
133 #include "public/web/WebActiveWheelFlingParameters.h"
134 #include "public/web/WebAutofillClient.h"
135 #include "public/web/WebBeginFrameArgs.h"
136 #include "public/web/WebElement.h"
137 #include "public/web/WebFrame.h"
138 #include "public/web/WebFrameClient.h"
139 #include "public/web/WebGraphicsContext.h"
140 #include "public/web/WebHitTestResult.h"
141 #include "public/web/WebInputElement.h"
142 #include "public/web/WebMediaPlayerAction.h"
143 #include "public/web/WebNode.h"
144 #include "public/web/WebPlugin.h"
145 #include "public/web/WebPluginAction.h"
146 #include "public/web/WebRange.h"
147 #include "public/web/WebSelection.h"
148 #include "public/web/WebTextInputInfo.h"
149 #include "public/web/WebViewClient.h"
150 #include "public/web/WebWindowFeatures.h"
151 #include "web/CompositionUnderlineVectorBuilder.h"
152 #include "web/ContextFeaturesClientImpl.h"
153 #include "web/ContextMenuAllowedScope.h"
154 #include "web/DatabaseClientImpl.h"
155 #include "web/DevToolsEmulator.h"
156 #include "web/FullscreenController.h"
157 #include "web/GraphicsLayerFactoryChromium.h"
158 #include "web/InspectorOverlayImpl.h"
159 #include "web/LinkHighlightImpl.h"
160 #include "web/PageOverlay.h"
161 #include "web/PrerendererClientImpl.h"
162 #include "web/ResizeViewportAnchor.h"
163 #include "web/RotationViewportAnchor.h"
164 #include "web/SpeechRecognitionClientProxy.h"
165 #include "web/StorageQuotaClientImpl.h"
166 #include "web/ValidationMessageClientImpl.h"
167 #include "web/ViewportAnchor.h"
168 #include "web/WebDevToolsAgentImpl.h"
169 #include "web/WebInputEventConversion.h"
170 #include "web/WebLocalFrameImpl.h"
171 #include "web/WebPagePopupImpl.h"
172 #include "web/WebPluginContainerImpl.h"
173 #include "web/WebRemoteFrameImpl.h"
174 #include "web/WebSettingsImpl.h"
175 #include "web/WorkerGlobalScopeProxyProviderImpl.h"
176 #include "wtf/CurrentTime.h"
177 #include "wtf/RefPtr.h"
178 #include "wtf/TemporaryChange.h"
180 #if USE(DEFAULT_RENDER_THEME)
181 #include "core/layout/LayoutThemeDefault.h"
184 // Get rid of WTF's pow define so we can use std::pow.
186 #include <cmath> // for std::pow
188 // The following constants control parameters for automated scaling of webpages
189 // (such as due to a double tap gesture or find in page etc.). These are
190 // experimentally determined.
191 static const int touchPointPadding
= 32;
192 static const int nonUserInitiatedPointPadding
= 11;
193 static const float minScaleDifference
= 0.01f
;
194 static const float doubleTapZoomContentDefaultMargin
= 5;
195 static const float doubleTapZoomContentMinimumMargin
= 2;
196 static const double doubleTapZoomAnimationDurationInSeconds
= 0.25;
197 static const float doubleTapZoomAlreadyLegibleRatio
= 1.2f
;
199 static const double multipleTargetsZoomAnimationDurationInSeconds
= 0.25;
200 static const double findInPageAnimationDurationInSeconds
= 0;
202 // Constants for viewport anchoring on resize.
203 static const float viewportAnchorCoordX
= 0.5f
;
204 static const float viewportAnchorCoordY
= 0;
206 // Constants for zooming in on a focused text field.
207 static const double scrollAndScaleAnimationDurationInSeconds
= 0.2;
208 static const int minReadableCaretHeight
= 16;
209 static const int minReadableCaretHeightForTextArea
= 13;
210 static const float minScaleChangeToTriggerZoom
= 1.5f
;
211 static const float leftBoxRatio
= 0.3f
;
212 static const int caretPadding
= 10;
216 // Change the text zoom level by kTextSizeMultiplierRatio each time the user
217 // zooms text in or out (ie., change by 20%). The min and max values limit
218 // text zoom to half and 3x the original text size. These three values match
219 // those in Apple's port in WebKit/WebKit/WebView/WebView.mm
220 const double WebView::textSizeMultiplierRatio
= 1.2;
221 const double WebView::minTextSizeMultiplier
= 0.5;
222 const double WebView::maxTextSizeMultiplier
= 3.0;
224 // Used to defer all page activity in cases where the embedder wishes to run
225 // a nested event loop. Using a stack enables nesting of message loop invocations.
226 static Vector
<OwnPtr
<ScopedPageLoadDeferrer
>>& pageLoadDeferrerStack()
228 DEFINE_STATIC_LOCAL(Vector
<OwnPtr
<ScopedPageLoadDeferrer
>>, deferrerStack
, ());
229 return deferrerStack
;
232 // Ensure that the WebDragOperation enum values stay in sync with the original
233 // DragOperation constants.
234 #define STATIC_ASSERT_MATCHING_ENUM(coreName) \
235 static_assert(int(coreName) == int(Web##coreName), "DragOperation and WebDragOperation enum mismatch: " #coreName)
236 STATIC_ASSERT_MATCHING_ENUM(DragOperationNone
);
237 STATIC_ASSERT_MATCHING_ENUM(DragOperationCopy
);
238 STATIC_ASSERT_MATCHING_ENUM(DragOperationLink
);
239 STATIC_ASSERT_MATCHING_ENUM(DragOperationGeneric
);
240 STATIC_ASSERT_MATCHING_ENUM(DragOperationPrivate
);
241 STATIC_ASSERT_MATCHING_ENUM(DragOperationMove
);
242 STATIC_ASSERT_MATCHING_ENUM(DragOperationDelete
);
243 STATIC_ASSERT_MATCHING_ENUM(DragOperationEvery
);
245 static bool shouldUseExternalPopupMenus
= false;
249 class UserGestureNotifier
{
251 // If a UserGestureIndicator is created for a user gesture since the last
252 // page load and *userGestureObserved is false, the UserGestureNotifier
253 // will notify the client and set *userGestureObserved to true.
254 UserGestureNotifier(WebAutofillClient
*, bool* userGestureObserved
);
255 ~UserGestureNotifier();
258 WebAutofillClient
* const m_client
;
259 bool* const m_userGestureObserved
;
262 UserGestureNotifier::UserGestureNotifier(WebAutofillClient
* client
, bool* userGestureObserved
)
264 , m_userGestureObserved(userGestureObserved
)
266 ASSERT(m_userGestureObserved
);
269 UserGestureNotifier::~UserGestureNotifier()
271 if (!*m_userGestureObserved
&& UserGestureIndicator::processedUserGestureSinceLoad()) {
272 *m_userGestureObserved
= true;
274 m_client
->firstUserGestureObserved();
278 class EmptyEventListener final
: public EventListener
{
280 static PassRefPtrWillBeRawPtr
<EmptyEventListener
> create()
282 return adoptRefWillBeNoop(new EmptyEventListener());
285 bool operator==(const EventListener
& other
) override
287 return this == &other
;
292 : EventListener(CPPEventListenerType
)
296 void handleEvent(ExecutionContext
* executionContext
, Event
*) override
301 class ColorOverlay final
: public PageOverlay::Delegate
{
303 explicit ColorOverlay(WebColor color
)
308 virtual ~ColorOverlay()
313 void paintPageOverlay(WebGraphicsContext
* context
, const WebSize
& size
)
315 WebFloatRect
rect(0, 0, size
.width
, size
.height
);
316 WebCanvas
* canvas
= context
->beginDrawing(rect
);
318 paint
.setColor(m_color
);
319 paint
.setStyle(SkPaint::kFill_Style
);
320 canvas
->drawRectCoords(0, 0, size
.width
, size
.height
, paint
);
321 context
->endDrawing();
329 // WebView ----------------------------------------------------------------
331 WebView
* WebView::create(WebViewClient
* client
)
333 // Pass the WebViewImpl's self-reference to the caller.
334 return WebViewImpl::create(client
);
337 WebViewImpl
* WebViewImpl::create(WebViewClient
* client
)
339 // Pass the WebViewImpl's self-reference to the caller.
340 return adoptRef(new WebViewImpl(client
)).leakRef();
343 void WebView::setUseExternalPopupMenus(bool useExternalPopupMenus
)
345 shouldUseExternalPopupMenus
= useExternalPopupMenus
;
348 void WebView::updateVisitedLinkState(unsigned long long linkHash
)
350 Page::visitedStateChanged(linkHash
);
353 void WebView::resetVisitedLinkState()
355 Page::allVisitedStateChanged();
358 void WebView::willEnterModalLoop()
360 pageLoadDeferrerStack().append(adoptPtr(new ScopedPageLoadDeferrer()));
363 void WebView::didExitModalLoop()
365 ASSERT(pageLoadDeferrerStack().size());
366 pageLoadDeferrerStack().removeLast();
369 void WebViewImpl::setMainFrame(WebFrame
* frame
)
371 if (frame
->isWebLocalFrame()) {
372 WebLocalFrameImpl
* localFrame
= toWebLocalFrameImpl(frame
);
373 localFrame
->initializeCoreFrame(&page()->frameHost(), 0, nullAtom
, nullAtom
);
374 // Composited WebViews want repaints outside the frame visible rect.
375 localFrame
->frame()->view()->setClipsRepaints(!m_layerTreeView
);
377 toWebRemoteFrameImpl(frame
)->initializeCoreFrame(&page()->frameHost(), 0, nullAtom
);
381 void WebViewImpl::setCredentialManagerClient(WebCredentialManagerClient
* webCredentialManagerClient
)
384 provideCredentialManagerClientTo(*m_page
, new CredentialManagerClient(webCredentialManagerClient
));
387 void WebViewImpl::setPrerendererClient(WebPrerendererClient
* prerendererClient
)
390 providePrerendererClientTo(*m_page
, new PrerendererClientImpl(prerendererClient
));
393 void WebViewImpl::setSpellCheckClient(WebSpellCheckClient
* spellCheckClient
)
395 m_spellCheckClient
= spellCheckClient
;
399 HashSet
<WebViewImpl
*>& WebViewImpl::allInstances()
401 DEFINE_STATIC_LOCAL(HashSet
<WebViewImpl
*>, allInstances
, ());
405 WebViewImpl::WebViewImpl(WebViewClient
* client
)
407 , m_spellCheckClient(0)
408 , m_chromeClientImpl(ChromeClientImpl::create(this))
409 , m_contextMenuClientImpl(this)
410 , m_dragClientImpl(this)
411 , m_editorClientImpl(this)
412 , m_spellCheckerClientImpl(this)
413 , m_storageClientImpl(this)
414 , m_shouldAutoResize(false)
416 , m_minimumZoomLevel(zoomFactorToZoomLevel(minTextSizeMultiplier
))
417 , m_maximumZoomLevel(zoomFactorToZoomLevel(maxTextSizeMultiplier
))
418 , m_maximumLegibleScale(1)
419 , m_doubleTapZoomPageScaleFactor(0)
420 , m_doubleTapZoomPending(false)
421 , m_enableFakePageScaleAnimationForTesting(false)
422 , m_fakePageScaleAnimationPageScaleFactor(0)
423 , m_fakePageScaleAnimationUseAnchor(false)
424 , m_doingDragAndDrop(false)
425 , m_ignoreInputEvents(false)
426 , m_compositorDeviceScaleFactorOverride(0)
427 , m_rootLayerScale(1)
428 , m_suppressNextKeypressEvent(false)
429 , m_imeAcceptEvents(true)
430 , m_operationsAllowed(WebDragOperationNone
)
431 , m_dragOperation(WebDragOperationNone
)
432 , m_devToolsEmulator(nullptr)
433 , m_isTransparent(false)
434 , m_tabsToLinks(false)
437 , m_rootGraphicsLayer(0)
438 , m_rootTransformLayer(0)
439 , m_graphicsLayerFactory(adoptPtr(new GraphicsLayerFactoryChromium(this)))
440 , m_matchesHeuristicsForGpuRasterization(false)
441 , m_recreatingGraphicsContext(false)
443 , m_flingSourceDevice(false)
444 , m_fullscreenController(FullscreenController::create(this))
445 , m_showFPSCounter(false)
446 , m_baseBackgroundColor(Color::white
)
447 , m_backgroundColorOverride(Color::transparent
)
448 , m_zoomFactorOverride(0)
449 , m_userGestureObserved(false)
450 , m_shouldDispatchFirstVisuallyNonEmptyLayout(false)
451 , m_shouldDispatchFirstLayoutAfterFinishedParsing(false)
452 , m_displayMode(WebDisplayModeBrowser
)
453 , m_elasticOverscroll(FloatSize())
455 Page::PageClients pageClients
;
456 pageClients
.chromeClient
= m_chromeClientImpl
.get();
457 pageClients
.contextMenuClient
= &m_contextMenuClientImpl
;
458 pageClients
.editorClient
= &m_editorClientImpl
;
459 pageClients
.dragClient
= &m_dragClientImpl
;
460 pageClients
.spellCheckerClient
= &m_spellCheckerClientImpl
;
462 m_page
= adoptPtrWillBeNoop(new Page(pageClients
));
463 MediaKeysController::provideMediaKeysTo(*m_page
, &m_mediaKeysClientImpl
);
464 provideSpeechRecognitionTo(*m_page
, SpeechRecognitionClientProxy::create(client
? client
->speechRecognizer() : 0));
465 provideContextFeaturesTo(*m_page
, ContextFeaturesClientImpl::create());
466 provideDatabaseClientTo(*m_page
, DatabaseClientImpl::create());
468 provideStorageQuotaClientTo(*m_page
, StorageQuotaClientImpl::create());
469 m_page
->setValidationMessageClient(ValidationMessageClientImpl::create(*this));
470 provideWorkerGlobalScopeProxyProviderTo(*m_page
, WorkerGlobalScopeProxyProviderImpl::create());
471 StorageNamespaceController::provideStorageNamespaceTo(*m_page
, &m_storageClientImpl
);
473 m_page
->makeOrdinary();
476 setDeviceScaleFactor(m_client
->screenInfo().deviceScaleFactor
);
477 setVisibilityState(m_client
->visibilityState(), true);
480 initializeLayerTreeView();
482 m_devToolsEmulator
= DevToolsEmulator::create(this);
484 allInstances().add(this);
486 m_pageImportanceSignals
.setObserver(client
);
489 WebViewImpl::~WebViewImpl()
494 WebDevToolsAgentImpl
* WebViewImpl::mainFrameDevToolsAgentImpl()
496 WebLocalFrameImpl
* mainFrame
= mainFrameImpl();
497 return mainFrame
? mainFrame
->devToolsAgentImpl() : nullptr;
500 InspectorOverlayImpl
* WebViewImpl::inspectorOverlay()
502 if (WebDevToolsAgentImpl
* devtools
= mainFrameDevToolsAgentImpl())
503 return static_cast<InspectorOverlayImpl
*>(devtools
->overlay());
507 WebLocalFrameImpl
* WebViewImpl::mainFrameImpl()
509 return m_page
&& m_page
->mainFrame() && m_page
->mainFrame()->isLocalFrame() ? WebLocalFrameImpl::fromFrame(m_page
->deprecatedLocalMainFrame()) : 0;
512 bool WebViewImpl::tabKeyCyclesThroughElements() const
515 return m_page
->tabKeyCyclesThroughElements();
518 void WebViewImpl::setTabKeyCyclesThroughElements(bool value
)
521 m_page
->setTabKeyCyclesThroughElements(value
);
524 void WebViewImpl::handleMouseLeave(LocalFrame
& mainFrame
, const WebMouseEvent
& event
)
526 m_client
->setMouseOverURL(WebURL());
527 PageWidgetEventHandler::handleMouseLeave(mainFrame
, event
);
530 void WebViewImpl::handleMouseDown(LocalFrame
& mainFrame
, const WebMouseEvent
& event
)
532 // If there is a popup open, close it as the user is clicking on the page
533 // (outside of the popup). We also save it so we can prevent a click on an
534 // element from immediately reopening the same popup.
535 RefPtr
<WebPagePopupImpl
> pagePopup
;
536 if (event
.button
== WebMouseEvent::ButtonLeft
) {
537 pagePopup
= m_pagePopup
;
539 ASSERT(!m_pagePopup
);
542 m_lastMouseDownPoint
= WebPoint(event
.x
, event
.y
);
544 // Take capture on a mouse down on a plugin so we can send it mouse events.
545 // If the hit node is a plugin but a scrollbar is over it don't start mouse
546 // capture because it will interfere with the scrollbar receiving events.
547 IntPoint
point(event
.x
, event
.y
);
548 if (event
.button
== WebMouseEvent::ButtonLeft
&& m_page
->mainFrame()->isLocalFrame()) {
549 point
= m_page
->deprecatedLocalMainFrame()->view()->rootFrameToContents(point
);
550 HitTestResult
result(m_page
->deprecatedLocalMainFrame()->eventHandler().hitTestResultAtPoint(point
));
551 result
.setToShadowHostIfInUserAgentShadowRoot();
552 Node
* hitNode
= result
.innerNodeOrImageMapImage();
554 if (!result
.scrollbar() && hitNode
&& hitNode
->layoutObject() && hitNode
->layoutObject()->isEmbeddedObject()) {
555 m_mouseCaptureNode
= hitNode
;
556 TRACE_EVENT_ASYNC_BEGIN0("input", "capturing mouse", this);
560 PageWidgetEventHandler::handleMouseDown(mainFrame
, event
);
562 if (event
.button
== WebMouseEvent::ButtonLeft
&& m_mouseCaptureNode
)
563 m_mouseCaptureGestureToken
= mainFrame
.eventHandler().takeLastMouseDownGestureToken();
565 if (m_pagePopup
&& pagePopup
&& m_pagePopup
->hasSamePopupClient(pagePopup
.get())) {
566 // That click triggered a page popup that is the same as the one we just closed.
567 // It needs to be closed.
571 // Dispatch the contextmenu event regardless of if the click was swallowed.
572 if (!page()->settings().showContextMenuOnMouseUp()) {
574 if (event
.button
== WebMouseEvent::ButtonRight
575 || (event
.button
== WebMouseEvent::ButtonLeft
576 && event
.modifiers
& WebMouseEvent::ControlKey
))
577 mouseContextMenu(event
);
579 if (event
.button
== WebMouseEvent::ButtonRight
)
580 mouseContextMenu(event
);
585 void WebViewImpl::setDisplayMode(WebDisplayMode mode
)
587 m_displayMode
= mode
;
588 if (!mainFrameImpl() || !mainFrameImpl()->frameView())
591 mainFrameImpl()->frameView()->setDisplayMode(mode
);
594 void WebViewImpl::mouseContextMenu(const WebMouseEvent
& event
)
596 if (!mainFrameImpl() || !mainFrameImpl()->frameView())
599 m_page
->contextMenuController().clearContextMenu();
601 PlatformMouseEventBuilder
pme(mainFrameImpl()->frameView(), event
);
603 // Find the right target frame. See issue 1186900.
604 HitTestResult result
= hitTestResultForRootFramePos(pme
.position());
606 if (result
.innerNodeOrImageMapImage())
607 targetFrame
= result
.innerNodeOrImageMapImage()->document().frame();
609 targetFrame
= m_page
->focusController().focusedOrMainFrame();
611 if (!targetFrame
->isLocalFrame())
614 LocalFrame
* targetLocalFrame
= toLocalFrame(targetFrame
);
617 targetLocalFrame
->view()->setCursor(pointerCursor());
621 ContextMenuAllowedScope scope
;
622 targetLocalFrame
->eventHandler().sendContextMenuEvent(pme
, nullptr);
624 // Actually showing the context menu is handled by the ContextMenuClient
628 void WebViewImpl::handleMouseUp(LocalFrame
& mainFrame
, const WebMouseEvent
& event
)
630 PageWidgetEventHandler::handleMouseUp(mainFrame
, event
);
632 if (page()->settings().showContextMenuOnMouseUp()) {
633 // Dispatch the contextmenu event regardless of if the click was swallowed.
634 // On Mac/Linux, we handle it on mouse down, not up.
635 if (event
.button
== WebMouseEvent::ButtonRight
)
636 mouseContextMenu(event
);
640 bool WebViewImpl::handleMouseWheel(LocalFrame
& mainFrame
, const WebMouseWheelEvent
& event
)
643 return PageWidgetEventHandler::handleMouseWheel(mainFrame
, event
);
646 bool WebViewImpl::scrollBy(const WebFloatSize
& delta
, const WebFloatSize
& velocity
)
648 if (m_flingSourceDevice
== WebGestureDeviceTouchpad
) {
649 WebMouseWheelEvent syntheticWheel
;
650 const float tickDivisor
= WheelEvent::TickMultiplier
;
652 syntheticWheel
.deltaX
= delta
.width
;
653 syntheticWheel
.deltaY
= delta
.height
;
654 syntheticWheel
.wheelTicksX
= delta
.width
/ tickDivisor
;
655 syntheticWheel
.wheelTicksY
= delta
.height
/ tickDivisor
;
656 syntheticWheel
.hasPreciseScrollingDeltas
= true;
657 syntheticWheel
.x
= m_positionOnFlingStart
.x
;
658 syntheticWheel
.y
= m_positionOnFlingStart
.y
;
659 syntheticWheel
.globalX
= m_globalPositionOnFlingStart
.x
;
660 syntheticWheel
.globalY
= m_globalPositionOnFlingStart
.y
;
661 syntheticWheel
.modifiers
= m_flingModifier
;
663 if (m_page
&& m_page
->mainFrame() && m_page
->mainFrame()->isLocalFrame() && m_page
->deprecatedLocalMainFrame()->view())
664 return handleMouseWheel(*m_page
->deprecatedLocalMainFrame(), syntheticWheel
);
666 WebGestureEvent syntheticGestureEvent
;
668 syntheticGestureEvent
.type
= WebInputEvent::GestureScrollUpdate
;
669 syntheticGestureEvent
.data
.scrollUpdate
.preventPropagation
= true;
670 syntheticGestureEvent
.data
.scrollUpdate
.deltaX
= delta
.width
;
671 syntheticGestureEvent
.data
.scrollUpdate
.deltaY
= delta
.height
;
672 syntheticGestureEvent
.data
.scrollUpdate
.velocityX
= velocity
.width
;
673 syntheticGestureEvent
.data
.scrollUpdate
.velocityY
= velocity
.height
;
674 syntheticGestureEvent
.x
= m_positionOnFlingStart
.x
;
675 syntheticGestureEvent
.y
= m_positionOnFlingStart
.y
;
676 syntheticGestureEvent
.globalX
= m_globalPositionOnFlingStart
.x
;
677 syntheticGestureEvent
.globalY
= m_globalPositionOnFlingStart
.y
;
678 syntheticGestureEvent
.modifiers
= m_flingModifier
;
679 syntheticGestureEvent
.sourceDevice
= WebGestureDeviceTouchscreen
;
680 syntheticGestureEvent
.data
.scrollUpdate
.inertial
= true;
682 if (m_page
&& m_page
->mainFrame() && m_page
->mainFrame()->isLocalFrame() && m_page
->deprecatedLocalMainFrame()->view())
683 return handleGestureEvent(syntheticGestureEvent
);
688 bool WebViewImpl::handleGestureEvent(const WebGestureEvent
& event
)
693 bool eventSwallowed
= false;
694 bool eventCancelled
= false; // for disambiguation
696 // Special handling for slow-path fling gestures.
697 switch (event
.type
) {
698 case WebInputEvent::GestureFlingStart
: {
699 if (mainFrameImpl()->frame()->eventHandler().isScrollbarHandlingGestures())
701 endActiveFlingAnimation();
702 m_client
->cancelScheduledContentIntents();
703 m_positionOnFlingStart
= WebPoint(event
.x
, event
.y
);
704 m_globalPositionOnFlingStart
= WebPoint(event
.globalX
, event
.globalY
);
705 m_flingModifier
= event
.modifiers
;
706 m_flingSourceDevice
= event
.sourceDevice
;
707 OwnPtr
<WebGestureCurve
> flingCurve
= adoptPtr(Platform::current()->createFlingAnimationCurve(event
.sourceDevice
, WebFloatPoint(event
.data
.flingStart
.velocityX
, event
.data
.flingStart
.velocityY
), WebSize()));
709 m_gestureAnimation
= WebActiveGestureAnimation::createAtAnimationStart(flingCurve
.release(), this);
711 eventSwallowed
= true;
713 // Plugins may need to see GestureFlingStart to balance
714 // GestureScrollBegin (since the former replaces GestureScrollEnd when
715 // transitioning to a fling).
716 PlatformGestureEventBuilder
platformEvent(mainFrameImpl()->frameView(), event
);
717 mainFrameImpl()->frame()->eventHandler().handleGestureScrollEvent(platformEvent
);
719 m_client
->didHandleGestureEvent(event
, eventCancelled
);
720 return eventSwallowed
;
722 case WebInputEvent::GestureFlingCancel
:
723 if (endActiveFlingAnimation())
724 eventSwallowed
= true;
726 m_client
->didHandleGestureEvent(event
, eventCancelled
);
727 return eventSwallowed
;
732 PlatformGestureEventBuilder
platformEvent(mainFrameImpl()->frameView(), event
);
734 // Special handling for double tap and scroll events as we don't want to
735 // hit test for them.
736 switch (event
.type
) {
737 case WebInputEvent::GestureDoubleTap
:
738 if (m_webSettings
->doubleTapToZoomEnabled() && minimumPageScaleFactor() != maximumPageScaleFactor()) {
739 m_client
->cancelScheduledContentIntents();
740 animateDoubleTapZoom(platformEvent
.position());
742 // GestureDoubleTap is currently only used by Android for zooming. For WebCore,
743 // GestureTap with tap count = 2 is used instead. So we drop GestureDoubleTap here.
744 eventSwallowed
= true;
745 m_client
->didHandleGestureEvent(event
, eventCancelled
);
746 return eventSwallowed
;
747 case WebInputEvent::GestureScrollBegin
:
748 m_client
->cancelScheduledContentIntents();
749 case WebInputEvent::GestureScrollEnd
:
750 case WebInputEvent::GestureScrollUpdate
:
751 case WebInputEvent::GestureFlingStart
:
752 // Scrolling-related gesture events invoke EventHandler recursively for each frame down
753 // the chain, doing a single-frame hit-test per frame. This matches handleWheelEvent.
754 // Perhaps we could simplify things by rewriting scroll handling to work inner frame
755 // out, and then unify with other gesture events.
756 eventSwallowed
= mainFrameImpl()->frame()->eventHandler().handleGestureScrollEvent(platformEvent
);
757 m_client
->didHandleGestureEvent(event
, eventCancelled
);
758 return eventSwallowed
;
759 case WebInputEvent::GesturePinchBegin
:
760 case WebInputEvent::GesturePinchEnd
:
761 case WebInputEvent::GesturePinchUpdate
:
767 // Hit test across all frames and do touch adjustment as necessary for the event type.
768 GestureEventWithHitTestResults targetedEvent
=
769 m_page
->deprecatedLocalMainFrame()->eventHandler().targetGestureEvent(platformEvent
);
771 // Handle link highlighting outside the main switch to avoid getting lost in the
772 // complicated set of cases handled below.
773 switch (event
.type
) {
774 case WebInputEvent::GestureShowPress
:
775 // Queue a highlight animation, then hand off to regular handler.
776 enableTapHighlightAtPoint(targetedEvent
);
778 case WebInputEvent::GestureTapCancel
:
779 case WebInputEvent::GestureTap
:
780 case WebInputEvent::GestureLongPress
:
781 for (size_t i
= 0; i
< m_linkHighlights
.size(); ++i
)
782 m_linkHighlights
[i
]->startHighlightAnimationIfNeeded();
788 switch (event
.type
) {
789 case WebInputEvent::GestureTap
: {
791 m_client
->cancelScheduledContentIntents();
792 if (detectContentOnTouch(targetedEvent
)) {
793 eventSwallowed
= true;
797 // Don't trigger a disambiguation popup on sites designed for mobile devices.
798 // Instead, assume that the page has been designed with big enough buttons and links.
799 // Don't trigger a disambiguation popup when screencasting, since it's implemented outside of
800 // compositor pipeline and is not being screencasted itself. This leads to bad user experience.
801 WebDevToolsAgentImpl
* devTools
= mainFrameDevToolsAgentImpl();
802 bool screencastEnabled
= devTools
&& devTools
->screencastEnabled();
803 if (event
.data
.tap
.width
> 0 && !shouldDisableDesktopWorkarounds() && !screencastEnabled
) {
804 IntRect
boundingBox(page()->frameHost().visualViewport().viewportToRootFrame(IntRect(
805 event
.x
- event
.data
.tap
.width
/ 2,
806 event
.y
- event
.data
.tap
.height
/ 2,
807 event
.data
.tap
.width
,
808 event
.data
.tap
.height
)));
810 // FIXME: We shouldn't pass details of the VisualViewport offset to render_view_impl.
811 WebSize visualViewportOffset
= flooredIntSize(page()->frameHost().visualViewport().location());
813 if (m_webSettings
->multiTargetTapNotificationEnabled()) {
814 Vector
<IntRect
> goodTargets
;
815 WillBeHeapVector
<RawPtrWillBeMember
<Node
>> highlightNodes
;
816 findGoodTouchTargets(boundingBox
, mainFrameImpl()->frame(), goodTargets
, highlightNodes
);
817 // FIXME: replace touch adjustment code when numberOfGoodTargets == 1?
818 // Single candidate case is currently handled by: https://bugs.webkit.org/show_bug.cgi?id=85101
819 if (goodTargets
.size() >= 2 && m_client
820 && m_client
->didTapMultipleTargets(visualViewportOffset
, boundingBox
, goodTargets
)) {
822 enableTapHighlights(highlightNodes
);
823 for (size_t i
= 0; i
< m_linkHighlights
.size(); ++i
)
824 m_linkHighlights
[i
]->startHighlightAnimationIfNeeded();
825 eventSwallowed
= true;
826 eventCancelled
= true;
832 eventSwallowed
= mainFrameImpl()->frame()->eventHandler().handleGestureEvent(targetedEvent
);
835 case WebInputEvent::GestureTwoFingerTap
:
836 case WebInputEvent::GestureLongPress
:
837 case WebInputEvent::GestureLongTap
: {
838 if (!mainFrameImpl() || !mainFrameImpl()->frameView())
841 m_client
->cancelScheduledContentIntents();
842 m_page
->contextMenuController().clearContextMenu();
844 ContextMenuAllowedScope scope
;
845 eventSwallowed
= mainFrameImpl()->frame()->eventHandler().handleGestureEvent(targetedEvent
);
850 case WebInputEvent::GestureShowPress
:
851 m_client
->cancelScheduledContentIntents();
852 case WebInputEvent::GestureTapDown
:
853 case WebInputEvent::GestureTapCancel
:
854 case WebInputEvent::GestureTapUnconfirmed
: {
855 eventSwallowed
= mainFrameImpl()->frame()->eventHandler().handleGestureEvent(targetedEvent
);
859 ASSERT_NOT_REACHED();
861 m_client
->didHandleGestureEvent(event
, eventCancelled
);
862 return eventSwallowed
;
865 bool WebViewImpl::handleSyntheticWheelFromTouchpadPinchEvent(const WebGestureEvent
& pinchEvent
)
867 ASSERT(pinchEvent
.type
== WebInputEvent::GesturePinchUpdate
);
869 // Touchscreen pinch events should not reach Blink.
870 ASSERT(pinchEvent
.sourceDevice
== WebGestureDeviceTouchpad
);
872 // For pinch gesture events, match typical trackpad behavior on Windows by sending fake
873 // wheel events with the ctrl modifier set when we see trackpad pinch gestures. Ideally
874 // we'd someday get a platform 'pinch' event and send that instead.
875 WebMouseWheelEvent wheelEvent
;
876 wheelEvent
.type
= WebInputEvent::MouseWheel
;
877 wheelEvent
.timeStampSeconds
= pinchEvent
.timeStampSeconds
;
878 wheelEvent
.windowX
= wheelEvent
.x
= pinchEvent
.x
;
879 wheelEvent
.windowY
= wheelEvent
.y
= pinchEvent
.y
;
880 wheelEvent
.globalX
= pinchEvent
.globalX
;
881 wheelEvent
.globalY
= pinchEvent
.globalY
;
882 wheelEvent
.modifiers
=
883 pinchEvent
.modifiers
| WebInputEvent::ControlKey
;
884 wheelEvent
.deltaX
= 0;
886 // The function to convert scales to deltaY values is designed to be
887 // compatible with websites existing use of wheel events, and with existing
888 // Windows trackpad behavior. In particular, we want:
889 // - deltas should accumulate via addition: f(s1*s2)==f(s1)+f(s2)
890 // - deltas should invert via negation: f(1/s) == -f(s)
891 // - zoom in should be positive: f(s) > 0 iff s > 1
892 // - magnitude roughly matches wheels: f(2) > 25 && f(2) < 100
893 // - a formula that's relatively easy to use from JavaScript
894 // Note that 'wheel' event deltaY values have their sign inverted. So to
895 // convert a wheel deltaY back to a scale use Math.exp(-deltaY/100).
896 ASSERT(pinchEvent
.data
.pinchUpdate
.scale
> 0);
897 wheelEvent
.deltaY
= 100.0f
* log(pinchEvent
.data
.pinchUpdate
.scale
);
898 wheelEvent
.hasPreciseScrollingDeltas
= true;
899 wheelEvent
.wheelTicksX
= 0;
900 wheelEvent
.wheelTicksY
=
901 pinchEvent
.data
.pinchUpdate
.scale
> 1 ? 1 : -1;
902 wheelEvent
.canScroll
= false;
904 return handleInputEvent(wheelEvent
);
907 void WebViewImpl::transferActiveWheelFlingAnimation(const WebActiveWheelFlingParameters
& parameters
)
909 TRACE_EVENT0("blink", "WebViewImpl::transferActiveWheelFlingAnimation");
910 ASSERT(!m_gestureAnimation
);
911 m_positionOnFlingStart
= parameters
.point
;
912 m_globalPositionOnFlingStart
= parameters
.globalPoint
;
913 m_flingModifier
= parameters
.modifiers
;
914 OwnPtr
<WebGestureCurve
> curve
= adoptPtr(Platform::current()->createFlingAnimationCurve(parameters
.sourceDevice
, WebFloatPoint(parameters
.delta
), parameters
.cumulativeScroll
));
916 m_gestureAnimation
= WebActiveGestureAnimation::createWithTimeOffset(curve
.release(), this, parameters
.startTime
);
920 bool WebViewImpl::endActiveFlingAnimation()
922 if (m_gestureAnimation
) {
923 m_gestureAnimation
.clear();
925 m_layerTreeView
->didStopFlinging();
931 bool WebViewImpl::startPageScaleAnimation(const IntPoint
& targetPosition
, bool useAnchor
, float newScale
, double durationInSeconds
)
933 VisualViewport
& visualViewport
= page()->frameHost().visualViewport();
934 WebPoint clampedPoint
= targetPosition
;
936 clampedPoint
= visualViewport
.clampDocumentOffsetAtScale(targetPosition
, newScale
);
937 if (!durationInSeconds
) {
938 setPageScaleFactor(newScale
);
940 FrameView
* view
= mainFrameImpl()->frameView();
941 if (view
&& view
->scrollableArea())
942 view
->scrollableArea()->setScrollPosition(DoublePoint(clampedPoint
.x
, clampedPoint
.y
), ProgrammaticScroll
);
947 if (useAnchor
&& newScale
== pageScaleFactor())
950 if (m_enableFakePageScaleAnimationForTesting
) {
951 m_fakePageScaleAnimationTargetPosition
= targetPosition
;
952 m_fakePageScaleAnimationUseAnchor
= useAnchor
;
953 m_fakePageScaleAnimationPageScaleFactor
= newScale
;
955 if (!m_layerTreeView
)
957 m_layerTreeView
->startPageScaleAnimation(targetPosition
, useAnchor
, newScale
, durationInSeconds
);
962 void WebViewImpl::enableFakePageScaleAnimationForTesting(bool enable
)
964 m_enableFakePageScaleAnimationForTesting
= enable
;
967 void WebViewImpl::setShowFPSCounter(bool show
)
969 if (m_layerTreeView
) {
970 TRACE_EVENT0("blink", "WebViewImpl::setShowFPSCounter");
971 m_layerTreeView
->setShowFPSCounter(show
&& !m_devToolsEmulator
->deviceEmulationEnabled());
973 m_showFPSCounter
= show
;
976 void WebViewImpl::setShowPaintRects(bool show
)
978 if (m_layerTreeView
) {
979 TRACE_EVENT0("blink", "WebViewImpl::setShowPaintRects");
980 m_layerTreeView
->setShowPaintRects(show
);
982 setFirstPaintInvalidationTrackingEnabledForShowPaintRects(show
);
985 void WebViewImpl::setShowDebugBorders(bool show
)
988 m_layerTreeView
->setShowDebugBorders(show
);
991 void WebViewImpl::updateShowFPSCounter()
994 m_layerTreeView
->setShowFPSCounter(m_showFPSCounter
&& !m_devToolsEmulator
->deviceEmulationEnabled());
997 void WebViewImpl::setShowScrollBottleneckRects(bool show
)
1000 m_layerTreeView
->setShowScrollBottleneckRects(show
);
1003 void WebViewImpl::acceptLanguagesChanged()
1008 page()->acceptLanguagesChanged();
1011 bool WebViewImpl::handleKeyEvent(const WebKeyboardEvent
& event
)
1013 ASSERT((event
.type
== WebInputEvent::RawKeyDown
)
1014 || (event
.type
== WebInputEvent::KeyDown
)
1015 || (event
.type
== WebInputEvent::KeyUp
));
1017 // Halt an in-progress fling on a key event.
1018 endActiveFlingAnimation();
1020 // Please refer to the comments explaining the m_suppressNextKeypressEvent
1022 // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
1023 // Webkit. A keyDown event is typically associated with a keyPress(char)
1024 // event and a keyUp event. We reset this flag here as this is a new keyDown
1026 m_suppressNextKeypressEvent
= false;
1028 // If there is a popup, it should be the one processing the event, not the
1031 m_pagePopup
->handleKeyEvent(PlatformKeyboardEventBuilder(event
));
1032 // We need to ignore the next Char event after this otherwise pressing
1033 // enter when selecting an item in the popup will go to the page.
1034 if (WebInputEvent::RawKeyDown
== event
.type
)
1035 m_suppressNextKeypressEvent
= true;
1039 RefPtrWillBeRawPtr
<Frame
> focusedFrame
= focusedCoreFrame();
1040 if (focusedFrame
&& focusedFrame
->isRemoteFrame()) {
1041 WebRemoteFrameImpl
* webFrame
= WebRemoteFrameImpl::fromFrame(*toRemoteFrame(focusedFrame
.get()));
1042 webFrame
->client()->forwardInputEvent(&event
);
1046 if (!focusedFrame
|| !focusedFrame
->isLocalFrame())
1049 LocalFrame
* frame
= toLocalFrame(focusedFrame
.get());
1051 PlatformKeyboardEventBuilder
evt(event
);
1053 if (frame
->eventHandler().keyEvent(evt
)) {
1054 if (WebInputEvent::RawKeyDown
== event
.type
) {
1055 // Suppress the next keypress event unless the focused node is a plugin node.
1056 // (Flash needs these keypress events to handle non-US keyboards.)
1057 Element
* element
= focusedElement();
1058 if (element
&& element
->layoutObject() && element
->layoutObject()->isEmbeddedObject()) {
1059 if (event
.windowsKeyCode
== VKEY_TAB
) {
1060 // If the plugin supports keyboard focus then we should not send a tab keypress event.
1061 Widget
* widget
= toLayoutPart(element
->layoutObject())->widget();
1062 if (widget
&& widget
->isPluginContainer()) {
1063 WebPluginContainerImpl
* plugin
= toWebPluginContainerImpl(widget
);
1064 if (plugin
&& plugin
->supportsKeyboardFocus())
1065 m_suppressNextKeypressEvent
= true;
1069 m_suppressNextKeypressEvent
= true;
1076 const WebInputEvent::Type contextMenuTriggeringEventType
=
1078 WebInputEvent::KeyUp
;
1080 WebInputEvent::RawKeyDown
;
1083 bool isUnmodifiedMenuKey
= !(event
.modifiers
& WebInputEvent::InputModifiers
) && event
.windowsKeyCode
== VKEY_APPS
;
1084 bool isShiftF10
= event
.modifiers
== WebInputEvent::ShiftKey
&& event
.windowsKeyCode
== VKEY_F10
;
1085 if ((isUnmodifiedMenuKey
|| isShiftF10
) && event
.type
== contextMenuTriggeringEventType
) {
1086 sendContextMenuEvent(event
);
1089 #endif // !OS(MACOSX)
1091 return keyEventDefault(event
);
1094 bool WebViewImpl::handleCharEvent(const WebKeyboardEvent
& event
)
1096 ASSERT(event
.type
== WebInputEvent::Char
);
1098 // Please refer to the comments explaining the m_suppressNextKeypressEvent
1099 // member. The m_suppressNextKeypressEvent is set if the KeyDown is
1100 // handled by Webkit. A keyDown event is typically associated with a
1101 // keyPress(char) event and a keyUp event. We reset this flag here as it
1102 // only applies to the current keyPress event.
1103 bool suppress
= m_suppressNextKeypressEvent
;
1104 m_suppressNextKeypressEvent
= false;
1106 // If there is a popup, it should be the one processing the event, not the
1109 return m_pagePopup
->handleKeyEvent(PlatformKeyboardEventBuilder(event
));
1111 LocalFrame
* frame
= toLocalFrame(focusedCoreFrame());
1115 EventHandler
& handler
= frame
->eventHandler();
1117 PlatformKeyboardEventBuilder
evt(event
);
1118 if (!evt
.isCharacterKey())
1121 // Accesskeys are triggered by char events and can't be suppressed.
1122 if (handler
.handleAccessKey(evt
))
1125 // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
1126 // the eventHandler::keyEvent. We mimic this behavior on all platforms since
1127 // for now we are converting other platform's key events to windows key
1129 if (evt
.isSystemKey())
1132 if (!suppress
&& !handler
.keyEvent(evt
))
1133 return keyEventDefault(event
);
1138 WebRect
WebViewImpl::computeBlockBound(const WebPoint
& pointInRootFrame
, bool ignoreClipping
)
1140 if (!mainFrameImpl())
1143 // Use the point-based hit test to find the node.
1144 IntPoint point
= mainFrameImpl()->frameView()->rootFrameToContents(IntPoint(pointInRootFrame
.x
, pointInRootFrame
.y
));
1145 HitTestRequest::HitTestRequestType hitType
= HitTestRequest::ReadOnly
| HitTestRequest::Active
| (ignoreClipping
? HitTestRequest::IgnoreClipping
: 0);
1146 HitTestResult result
= mainFrameImpl()->frame()->eventHandler().hitTestResultAtPoint(point
, hitType
);
1147 result
.setToShadowHostIfInUserAgentShadowRoot();
1149 Node
* node
= result
.innerNodeOrImageMapImage();
1153 // Find the block type node based on the hit node.
1154 // FIXME: This wants to walk composed tree with LayoutTreeBuilderTraversal::parent().
1155 while (node
&& (!node
->layoutObject() || node
->layoutObject()->isInline()))
1156 node
= LayoutTreeBuilderTraversal::parent(*node
);
1158 // Return the bounding box in the root frame's coordinate space.
1160 IntRect pointInRootFrame
= node
->Node::pixelSnappedBoundingBox();
1161 LocalFrame
* frame
= node
->document().frame();
1162 return frame
->view()->contentsToRootFrame(pointInRootFrame
);
1167 WebRect
WebViewImpl::widenRectWithinPageBounds(const WebRect
& source
, int targetMargin
, int minimumMargin
)
1171 maxSize
= mainFrame()->contentsSize();
1172 IntSize scrollOffset
;
1174 scrollOffset
= mainFrame()->scrollOffset();
1175 int leftMargin
= targetMargin
;
1176 int rightMargin
= targetMargin
;
1178 const int absoluteSourceX
= source
.x
+ scrollOffset
.width();
1179 if (leftMargin
> absoluteSourceX
) {
1180 leftMargin
= absoluteSourceX
;
1181 rightMargin
= std::max(leftMargin
, minimumMargin
);
1184 const int maximumRightMargin
= maxSize
.width
- (source
.width
+ absoluteSourceX
);
1185 if (rightMargin
> maximumRightMargin
) {
1186 rightMargin
= maximumRightMargin
;
1187 leftMargin
= std::min(leftMargin
, std::max(rightMargin
, minimumMargin
));
1190 const int newWidth
= source
.width
+ leftMargin
+ rightMargin
;
1191 const int newX
= source
.x
- leftMargin
;
1193 ASSERT(newWidth
>= 0);
1194 ASSERT(scrollOffset
.width() + newX
+ newWidth
<= maxSize
.width
);
1196 return WebRect(newX
, source
.y
, newWidth
, source
.height
);
1199 float WebViewImpl::maximumLegiblePageScale() const
1201 // Pages should be as legible as on desktop when at dpi scale, so no
1202 // need to zoom in further when automatically determining zoom level
1203 // (after double tap, find in page, etc), though the user should still
1204 // be allowed to manually pinch zoom in further if they desire.
1206 return m_maximumLegibleScale
* page()->settings().accessibilityFontScaleFactor();
1207 return m_maximumLegibleScale
;
1210 void WebViewImpl::computeScaleAndScrollForBlockRect(const WebPoint
& hitPointInRootFrame
, const WebRect
& blockRectInRootFrame
, float padding
, float defaultScaleWhenAlreadyLegible
, float& scale
, WebPoint
& scroll
)
1212 scale
= pageScaleFactor();
1213 scroll
.x
= scroll
.y
= 0;
1215 WebRect rect
= blockRectInRootFrame
;
1217 if (!rect
.isEmpty()) {
1218 float defaultMargin
= doubleTapZoomContentDefaultMargin
;
1219 float minimumMargin
= doubleTapZoomContentMinimumMargin
;
1220 // We want the margins to have the same physical size, which means we
1221 // need to express them in post-scale size. To do that we'd need to know
1222 // the scale we're scaling to, but that depends on the margins. Instead
1223 // we express them as a fraction of the target rectangle: this will be
1224 // correct if we end up fully zooming to it, and won't matter if we
1226 rect
= widenRectWithinPageBounds(rect
,
1227 static_cast<int>(defaultMargin
* rect
.width
/ m_size
.width
),
1228 static_cast<int>(minimumMargin
* rect
.width
/ m_size
.width
));
1229 // Fit block to screen, respecting limits.
1230 scale
= static_cast<float>(m_size
.width
) / rect
.width
;
1231 scale
= std::min(scale
, maximumLegiblePageScale());
1232 if (pageScaleFactor() < defaultScaleWhenAlreadyLegible
)
1233 scale
= std::max(scale
, defaultScaleWhenAlreadyLegible
);
1234 scale
= clampPageScaleFactorToLimits(scale
);
1237 // FIXME: If this is being called for auto zoom during find in page,
1238 // then if the user manually zooms in it'd be nice to preserve the
1239 // relative increase in zoom they caused (if they zoom out then it's ok
1240 // to zoom them back in again). This isn't compatible with our current
1241 // double-tap zoom strategy (fitting the containing block to the screen)
1244 float screenWidth
= m_size
.width
/ scale
;
1245 float screenHeight
= m_size
.height
/ scale
;
1247 // Scroll to vertically align the block.
1248 if (rect
.height
< screenHeight
) {
1249 // Vertically center short blocks.
1250 rect
.y
-= 0.5 * (screenHeight
- rect
.height
);
1252 // Ensure position we're zooming to (+ padding) isn't off the bottom of
1254 rect
.y
= std::max
<float>(rect
.y
, hitPointInRootFrame
.y
+ padding
- screenHeight
);
1255 } // Otherwise top align the block.
1257 // Do the same thing for horizontal alignment.
1258 if (rect
.width
< screenWidth
)
1259 rect
.x
-= 0.5 * (screenWidth
- rect
.width
);
1261 rect
.x
= std::max
<float>(rect
.x
, hitPointInRootFrame
.x
+ padding
- screenWidth
);
1265 scale
= clampPageScaleFactorToLimits(scale
);
1266 scroll
= mainFrameImpl()->frameView()->rootFrameToContents(scroll
);
1267 scroll
= page()->frameHost().visualViewport().clampDocumentOffsetAtScale(scroll
, scale
);
1270 static Node
* findCursorDefiningAncestor(Node
* node
, LocalFrame
* frame
)
1272 // Go up the tree to find the node that defines a mouse cursor style
1274 if (node
->layoutObject()) {
1275 ECursor cursor
= node
->layoutObject()->style()->cursor();
1276 if (cursor
!= CURSOR_AUTO
|| frame
->eventHandler().useHandCursor(node
, node
->isLink()))
1279 node
= LayoutTreeBuilderTraversal::parent(*node
);
1285 static bool showsHandCursor(Node
* node
, LocalFrame
* frame
)
1287 if (!node
|| !node
->layoutObject())
1290 ECursor cursor
= node
->layoutObject()->style()->cursor();
1291 return cursor
== CURSOR_POINTER
1292 || (cursor
== CURSOR_AUTO
&& frame
->eventHandler().useHandCursor(node
, node
->isLink()));
1295 Node
* WebViewImpl::bestTapNode(const GestureEventWithHitTestResults
& targetedTapEvent
)
1297 TRACE_EVENT0("input", "WebViewImpl::bestTapNode");
1299 if (!m_page
|| !m_page
->mainFrame())
1302 Node
* bestTouchNode
= targetedTapEvent
.hitTestResult().innerNode();
1306 // We might hit something like an image map that has no layoutObject on it
1307 // Walk up the tree until we have a node with an attached layoutObject
1308 while (!bestTouchNode
->layoutObject()) {
1309 bestTouchNode
= LayoutTreeBuilderTraversal::parent(*bestTouchNode
);
1314 // Editable nodes should not be highlighted (e.g., <input>)
1315 if (bestTouchNode
->hasEditableStyle())
1318 Node
* cursorDefiningAncestor
=
1319 findCursorDefiningAncestor(bestTouchNode
, m_page
->deprecatedLocalMainFrame());
1320 // We show a highlight on tap only when the current node shows a hand cursor
1321 if (!cursorDefiningAncestor
|| !showsHandCursor(cursorDefiningAncestor
, m_page
->deprecatedLocalMainFrame())) {
1325 // We should pick the largest enclosing node with hand cursor set. We do this by first jumping
1326 // up to cursorDefiningAncestor (which is already known to have hand cursor set). Then we locate
1327 // the next cursor-defining ancestor up in the the tree and repeat the jumps as long as the node
1328 // has hand cursor set.
1330 bestTouchNode
= cursorDefiningAncestor
;
1331 cursorDefiningAncestor
= findCursorDefiningAncestor(LayoutTreeBuilderTraversal::parent(*bestTouchNode
),
1332 m_page
->deprecatedLocalMainFrame());
1333 } while (cursorDefiningAncestor
&& showsHandCursor(cursorDefiningAncestor
, m_page
->deprecatedLocalMainFrame()));
1335 return bestTouchNode
;
1338 void WebViewImpl::enableTapHighlightAtPoint(const GestureEventWithHitTestResults
& targetedTapEvent
)
1340 Node
* touchNode
= bestTapNode(targetedTapEvent
);
1342 WillBeHeapVector
<RawPtrWillBeMember
<Node
>> highlightNodes
;
1343 highlightNodes
.append(touchNode
);
1345 enableTapHighlights(highlightNodes
);
1348 void WebViewImpl::enableTapHighlights(WillBeHeapVector
<RawPtrWillBeMember
<Node
>>& highlightNodes
)
1350 if (highlightNodes
.isEmpty())
1353 // Always clear any existing highlight when this is invoked, even if we
1354 // don't get a new target to highlight.
1355 m_linkHighlights
.clear();
1357 // LinkHighlight reads out layout and compositing state, so we need to make sure that's all up to date.
1360 for (size_t i
= 0; i
< highlightNodes
.size(); ++i
) {
1361 Node
* node
= highlightNodes
[i
];
1363 if (!node
|| !node
->layoutObject())
1366 Color highlightColor
= node
->layoutObject()->style()->tapHighlightColor();
1367 // Safari documentation for -webkit-tap-highlight-color says if the specified color has 0 alpha,
1368 // then tap highlighting is disabled.
1369 // http://developer.apple.com/library/safari/#documentation/appleapplications/reference/safaricssref/articles/standardcssproperties.html
1370 if (!highlightColor
.alpha())
1373 m_linkHighlights
.append(LinkHighlightImpl::create(node
, this));
1377 void WebViewImpl::animateDoubleTapZoom(const IntPoint
& pointInRootFrame
)
1379 if (!mainFrameImpl())
1382 WebRect blockBounds
= computeBlockBound(pointInRootFrame
, false);
1386 computeScaleAndScrollForBlockRect(pointInRootFrame
, blockBounds
, touchPointPadding
, minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio
, scale
, scroll
);
1388 bool stillAtPreviousDoubleTapScale
= (pageScaleFactor() == m_doubleTapZoomPageScaleFactor
1389 && m_doubleTapZoomPageScaleFactor
!= minimumPageScaleFactor())
1390 || m_doubleTapZoomPending
;
1392 bool scaleUnchanged
= fabs(pageScaleFactor() - scale
) < minScaleDifference
;
1393 bool shouldZoomOut
= blockBounds
.isEmpty() || scaleUnchanged
|| stillAtPreviousDoubleTapScale
;
1397 if (shouldZoomOut
) {
1398 scale
= minimumPageScaleFactor();
1399 isAnimating
= startPageScaleAnimation(mainFrameImpl()->frameView()->rootFrameToContents(pointInRootFrame
), true, scale
, doubleTapZoomAnimationDurationInSeconds
);
1401 isAnimating
= startPageScaleAnimation(scroll
, false, scale
, doubleTapZoomAnimationDurationInSeconds
);
1405 m_doubleTapZoomPageScaleFactor
= scale
;
1406 m_doubleTapZoomPending
= true;
1410 void WebViewImpl::zoomToFindInPageRect(const WebRect
& rectInRootFrame
)
1412 if (!mainFrameImpl())
1415 WebRect blockBounds
= computeBlockBound(WebPoint(rectInRootFrame
.x
+ rectInRootFrame
.width
/ 2, rectInRootFrame
.y
+ rectInRootFrame
.height
/ 2), true);
1417 if (blockBounds
.isEmpty()) {
1418 // Keep current scale (no need to scroll as x,y will normally already
1419 // be visible). FIXME: Revisit this if it isn't always true.
1426 computeScaleAndScrollForBlockRect(WebPoint(rectInRootFrame
.x
, rectInRootFrame
.y
), blockBounds
, nonUserInitiatedPointPadding
, minimumPageScaleFactor(), scale
, scroll
);
1428 startPageScaleAnimation(scroll
, false, scale
, findInPageAnimationDurationInSeconds
);
1431 bool WebViewImpl::zoomToMultipleTargetsRect(const WebRect
& rectInRootFrame
)
1433 if (!mainFrameImpl())
1439 computeScaleAndScrollForBlockRect(WebPoint(rectInRootFrame
.x
, rectInRootFrame
.y
), rectInRootFrame
, nonUserInitiatedPointPadding
, minimumPageScaleFactor(), scale
, scroll
);
1441 if (scale
<= pageScaleFactor())
1444 startPageScaleAnimation(scroll
, false, scale
, multipleTargetsZoomAnimationDurationInSeconds
);
1448 void WebViewImpl::hasTouchEventHandlers(bool hasTouchHandlers
)
1451 m_client
->hasTouchEventHandlers(hasTouchHandlers
);
1454 bool WebViewImpl::hasTouchEventHandlersAt(const WebPoint
& point
)
1456 // FIXME: Implement this. Note that the point must be divided by pageScaleFactor.
1461 // Mac has no way to open a context menu based on a keyboard event.
1462 bool WebViewImpl::sendContextMenuEvent(const WebKeyboardEvent
& event
)
1464 // The contextMenuController() holds onto the last context menu that was
1465 // popped up on the page until a new one is created. We need to clear
1466 // this menu before propagating the event through the DOM so that we can
1467 // detect if we create a new menu for this event, since we won't create
1468 // a new menu if the DOM swallows the event and the defaultEventHandler does
1470 page()->contextMenuController().clearContextMenu();
1474 ContextMenuAllowedScope scope
;
1475 Frame
* focusedFrame
= page()->focusController().focusedOrMainFrame();
1476 if (!focusedFrame
->isLocalFrame())
1478 handled
= toLocalFrame(focusedFrame
)->eventHandler().sendContextMenuEventForKey(nullptr);
1484 void WebViewImpl::showContextMenuAtPoint(float x
, float y
, PassRefPtrWillBeRawPtr
<ContextMenuProvider
> menuProvider
)
1486 if (!page()->mainFrame()->isLocalFrame())
1489 ContextMenuAllowedScope scope
;
1490 page()->contextMenuController().clearContextMenu();
1491 page()->contextMenuController().showContextMenuAtPoint(page()->deprecatedLocalMainFrame(), x
, y
, menuProvider
);
1495 void WebViewImpl::showContextMenuForElement(WebElement element
)
1500 page()->contextMenuController().clearContextMenu();
1502 ContextMenuAllowedScope scope
;
1503 if (LocalFrame
* focusedFrame
= toLocalFrame(page()->focusController().focusedOrMainFrame()))
1504 focusedFrame
->eventHandler().sendContextMenuEventForKey(element
.unwrap
<Element
>());
1508 bool WebViewImpl::keyEventDefault(const WebKeyboardEvent
& event
)
1510 LocalFrame
* frame
= toLocalFrame(focusedCoreFrame());
1514 switch (event
.type
) {
1515 case WebInputEvent::Char
:
1516 if (event
.windowsKeyCode
== VKEY_SPACE
) {
1517 int keyCode
= ((event
.modifiers
& WebInputEvent::ShiftKey
) ? VKEY_PRIOR
: VKEY_NEXT
);
1518 return scrollViewWithKeyboard(keyCode
, event
.modifiers
);
1521 case WebInputEvent::RawKeyDown
:
1522 if (event
.modifiers
== WebInputEvent::ControlKey
) {
1523 switch (event
.windowsKeyCode
) {
1526 focusedFrame()->executeCommand(WebString::fromUTF8("SelectAll"));
1530 focusedFrame()->executeCommand(WebString::fromUTF8("Copy"));
1533 // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl
1534 // key combinations which affect scrolling. Safari is buggy in the
1535 // sense that it scrolls the page for all Ctrl+scrolling key
1536 // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
1544 if (!event
.isSystemKey
&& !(event
.modifiers
& WebInputEvent::ShiftKey
))
1545 return scrollViewWithKeyboard(event
.windowsKeyCode
, event
.modifiers
);
1553 bool WebViewImpl::scrollViewWithKeyboard(int keyCode
, int modifiers
)
1555 ScrollDirectionPhysical scrollDirectionPhysical
;
1556 ScrollGranularity scrollGranularity
;
1558 // Control-Up/Down should be PageUp/Down on Mac.
1559 if (modifiers
& WebMouseEvent::ControlKey
) {
1560 if (keyCode
== VKEY_UP
)
1561 keyCode
= VKEY_PRIOR
;
1562 else if (keyCode
== VKEY_DOWN
)
1563 keyCode
= VKEY_NEXT
;
1566 if (!mapKeyCodeForScroll(keyCode
, &scrollDirectionPhysical
, &scrollGranularity
))
1569 if (LocalFrame
* frame
= toLocalFrame(focusedCoreFrame()))
1570 return frame
->eventHandler().bubblingScroll(toScrollDirection(scrollDirectionPhysical
), scrollGranularity
);
1574 bool WebViewImpl::mapKeyCodeForScroll(
1576 ScrollDirectionPhysical
* scrollDirection
,
1577 ScrollGranularity
* scrollGranularity
)
1581 *scrollDirection
= ScrollLeft
;
1582 *scrollGranularity
= ScrollByLine
;
1585 *scrollDirection
= ScrollRight
;
1586 *scrollGranularity
= ScrollByLine
;
1589 *scrollDirection
= ScrollUp
;
1590 *scrollGranularity
= ScrollByLine
;
1593 *scrollDirection
= ScrollDown
;
1594 *scrollGranularity
= ScrollByLine
;
1597 *scrollDirection
= ScrollUp
;
1598 *scrollGranularity
= ScrollByDocument
;
1601 *scrollDirection
= ScrollDown
;
1602 *scrollGranularity
= ScrollByDocument
;
1604 case VKEY_PRIOR
: // page up
1605 *scrollDirection
= ScrollUp
;
1606 *scrollGranularity
= ScrollByPage
;
1608 case VKEY_NEXT
: // page down
1609 *scrollDirection
= ScrollDown
;
1610 *scrollGranularity
= ScrollByPage
;
1619 PagePopup
* WebViewImpl::openPagePopup(PagePopupClient
* client
)
1622 if (hasOpenedPopup())
1624 ASSERT(!m_pagePopup
);
1626 WebWidget
* popupWidget
= m_client
->createPopupMenu(WebPopupTypePage
);
1627 ASSERT(popupWidget
);
1628 m_pagePopup
= toWebPagePopupImpl(popupWidget
);
1629 if (!m_pagePopup
->initialize(this, client
)) {
1630 m_pagePopup
->closePopup();
1631 m_pagePopup
= nullptr;
1633 enablePopupMouseWheelEventListener();
1634 return m_pagePopup
.get();
1637 void WebViewImpl::closePagePopup(PagePopup
* popup
)
1640 WebPagePopupImpl
* popupImpl
= toWebPagePopupImpl(popup
);
1641 ASSERT(m_pagePopup
.get() == popupImpl
);
1642 if (m_pagePopup
.get() != popupImpl
)
1644 m_pagePopup
->closePopup();
1645 m_pagePopup
= nullptr;
1646 disablePopupMouseWheelEventListener();
1649 void WebViewImpl::cancelPagePopup()
1652 m_pagePopup
->cancel();
1655 void WebViewImpl::enablePopupMouseWheelEventListener()
1657 ASSERT(!m_popupMouseWheelEventListener
);
1658 ASSERT(mainFrameImpl()->frame()->document());
1659 // We register an empty event listener, EmptyEventListener, so that mouse
1660 // wheel events get sent to the WebView.
1661 m_popupMouseWheelEventListener
= EmptyEventListener::create();
1662 mainFrameImpl()->frame()->document()->addEventListener(EventTypeNames::mousewheel
, m_popupMouseWheelEventListener
, false);
1665 void WebViewImpl::disablePopupMouseWheelEventListener()
1667 ASSERT(m_popupMouseWheelEventListener
);
1668 ASSERT(mainFrameImpl()->frame()->document());
1669 // Document may have already removed the event listener, for instance, due
1670 // to a navigation, but remove it anyway.
1671 mainFrameImpl()->frame()->document()->removeEventListener(EventTypeNames::mousewheel
, m_popupMouseWheelEventListener
.release(), false);
1674 LocalDOMWindow
* WebViewImpl::pagePopupWindow() const
1676 return m_pagePopup
? m_pagePopup
->window() : nullptr;
1679 Frame
* WebViewImpl::focusedCoreFrame() const
1681 return m_page
? m_page
->focusController().focusedOrMainFrame() : 0;
1684 WebViewImpl
* WebViewImpl::fromPage(Page
* page
)
1688 return static_cast<WebViewImpl
*>(page
->chromeClient().webView());
1691 // WebWidget ------------------------------------------------------------------
1693 void WebViewImpl::close()
1695 WebDevToolsAgentImpl::webViewImplClosed(this);
1696 ASSERT(allInstances().contains(this));
1697 allInstances().remove(this);
1700 // Initiate shutdown for the entire frameset. This will cause a lot of
1701 // notifications to be sent.
1702 m_page
->willBeDestroyed();
1706 // Reset the delegate to prevent notifications being sent as we're being
1710 deref(); // Balances ref() acquired in WebView::create
1713 void WebViewImpl::willStartLiveResize()
1715 if (mainFrameImpl() && mainFrameImpl()->frameView())
1716 mainFrameImpl()->frameView()->willStartLiveResize();
1719 WebSize
WebViewImpl::size()
1724 void WebViewImpl::resizeVisualViewport(const WebSize
& newSize
)
1726 page()->frameHost().visualViewport().setSize(newSize
);
1727 page()->frameHost().visualViewport().clampToBoundaries();
1730 void WebViewImpl::resizePinchViewport(const WebSize
& newSize
)
1732 resizeVisualViewport(newSize
);
1735 void WebViewImpl::performResize()
1737 pageScaleConstraintsSet().didChangeViewSize(m_size
);
1739 updatePageDefinedViewportConstraints(mainFrameImpl()->frame()->document()->viewportDescription());
1740 updateMainFrameLayoutSize();
1742 page()->frameHost().visualViewport().setSize(m_size
);
1744 if (mainFrameImpl()->frameView()) {
1745 if (!mainFrameImpl()->frameView()->needsLayout())
1746 postLayoutResize(mainFrameImpl());
1749 // When device emulation is enabled, device size values may change - they are
1750 // usually set equal to the view size. These values are not considered viewport-dependent
1751 // (see MediaQueryExp::isViewportDependent), since they are only viewport-dependent in emulation mode,
1752 // and thus will not be invalidated in |FrameView::performPreLayoutTasks|.
1753 // Therefore we should force explicit media queries invalidation here.
1754 if (m_devToolsEmulator
->deviceEmulationEnabled()) {
1755 if (Document
* document
= mainFrameImpl()->frame()->document())
1756 document
->mediaQueryAffectingValueChanged();
1760 void WebViewImpl::setTopControlsHeight(float height
, bool topControlsShrinkLayoutSize
)
1762 topControls().setHeight(height
, topControlsShrinkLayoutSize
);
1765 void WebViewImpl::updateTopControlsState(WebTopControlsState constraint
, WebTopControlsState current
, bool animate
)
1767 topControls().updateConstraints(constraint
);
1768 if (m_layerTreeView
)
1769 m_layerTreeView
->updateTopControlsState(constraint
, current
, animate
);
1772 void WebViewImpl::didUpdateTopControls()
1774 if (m_layerTreeView
) {
1775 m_layerTreeView
->setTopControlsShownRatio(topControls().shownRatio());
1776 m_layerTreeView
->setTopControlsHeight(topControls().height(), topControls().shrinkViewport());
1779 WebLocalFrameImpl
* mainFrame
= mainFrameImpl();
1783 FrameView
* view
= mainFrame
->frameView();
1787 VisualViewport
& visualViewport
= page()->frameHost().visualViewport();
1788 float topControlsViewportAdjustment
= topControls().layoutHeight() - topControls().contentOffset();
1789 visualViewport
.setTopControlsAdjustment(topControlsViewportAdjustment
);
1791 // Shrink the FrameView by the amount that will maintain the aspect-ratio with the VisualViewport.
1792 view
->setTopControlsViewportAdjustment(topControlsViewportAdjustment
/ minimumPageScaleFactor());
1795 TopControls
& WebViewImpl::topControls()
1797 return page()->frameHost().topControls();
1800 void WebViewImpl::resizeViewWhileAnchored(FrameView
* view
)
1802 // FIXME: TextAutosizer does not yet support out-of-process frames.
1803 if (mainFrameImpl() && mainFrameImpl()->frame()->isLocalFrame()) {
1804 // Avoids unnecessary invalidations while various bits of state in TextAutosizer are updated.
1805 TextAutosizer::DeferUpdatePageInfo
deferUpdatePageInfo(page());
1811 m_fullscreenController
->updateSize();
1813 // Relayout immediately to recalculate the minimum scale limit for rotation anchoring.
1814 if (view
->needsLayout())
1818 void WebViewImpl::resize(const WebSize
& newSize
)
1820 if (m_shouldAutoResize
|| m_size
== newSize
)
1823 WebLocalFrameImpl
* mainFrame
= mainFrameImpl();
1827 FrameView
* view
= mainFrame
->frameView();
1831 VisualViewport
& visualViewport
= page()->frameHost().visualViewport();
1833 bool isRotation
= settings()->mainFrameResizesAreOrientationChanges()
1834 && m_size
.width
&& contentsSize().width() && newSize
.width
!= m_size
.width
&& !m_fullscreenController
->isFullscreen();
1837 FloatSize
viewportAnchorCoords(viewportAnchorCoordX
, viewportAnchorCoordY
);
1839 RotationViewportAnchor
anchor(*view
, visualViewport
, viewportAnchorCoords
, pageScaleConstraintsSet());
1840 resizeViewWhileAnchored(view
);
1842 ResizeViewportAnchor
anchor(*view
, visualViewport
);
1843 resizeViewWhileAnchored(view
);
1845 sendResizeEventAndRepaint();
1848 void WebViewImpl::willEndLiveResize()
1850 if (mainFrameImpl() && mainFrameImpl()->frameView())
1851 mainFrameImpl()->frameView()->willEndLiveResize();
1854 void WebViewImpl::didEnterFullScreen()
1856 m_fullscreenController
->didEnterFullScreen();
1859 void WebViewImpl::didExitFullScreen()
1861 m_fullscreenController
->didExitFullScreen();
1864 void WebViewImpl::beginFrame(const WebBeginFrameArgs
& frameTime
)
1866 TRACE_EVENT0("blink", "WebViewImpl::beginFrame");
1868 WebBeginFrameArgs
validFrameTime(frameTime
);
1869 if (!validFrameTime
.lastFrameTimeMonotonic
)
1870 validFrameTime
.lastFrameTimeMonotonic
= monotonicallyIncreasingTime();
1872 // Create synthetic wheel events as necessary for fling.
1873 if (m_gestureAnimation
) {
1874 if (m_gestureAnimation
->animate(validFrameTime
.lastFrameTimeMonotonic
))
1875 scheduleAnimation();
1877 endActiveFlingAnimation();
1879 PlatformGestureEvent
endScrollEvent(PlatformEvent::GestureScrollEnd
,
1880 m_positionOnFlingStart
, m_globalPositionOnFlingStart
,
1881 IntSize(), 0, false, false, false, false);
1882 endScrollEvent
.setScrollGestureData(0, 0, 0, 0, true, false, -1 /* null plugin id */);
1884 mainFrameImpl()->frame()->eventHandler().handleGestureScrollEnd(endScrollEvent
);
1891 // FIXME: This should probably be using the local root?
1892 if (m_page
->mainFrame()->isLocalFrame())
1893 PageWidgetDelegate::animate(*m_page
, validFrameTime
.lastFrameTimeMonotonic
, *m_page
->deprecatedLocalMainFrame());
1896 void WebViewImpl::layout()
1898 TRACE_EVENT0("blink", "WebViewImpl::layout");
1899 if (!mainFrameImpl())
1902 PageWidgetDelegate::layout(*m_page
, *mainFrameImpl()->frame());
1903 updateLayerTreeBackgroundColor();
1904 if (InspectorOverlayImpl
* overlay
= inspectorOverlay())
1906 for (size_t i
= 0; i
< m_linkHighlights
.size(); ++i
)
1907 m_linkHighlights
[i
]->updateGeometry();
1909 if (FrameView
* view
= mainFrameImpl()->frameView()) {
1910 LocalFrame
* frame
= mainFrameImpl()->frame();
1912 if (m_shouldDispatchFirstVisuallyNonEmptyLayout
&& view
->isVisuallyNonEmpty()) {
1913 m_shouldDispatchFirstVisuallyNonEmptyLayout
= false;
1914 // TODO(esprehn): Move users of this callback to something
1915 // better, the heuristic for "visually non-empty" is bad.
1916 client()->didFirstVisuallyNonEmptyLayout();
1919 if (m_shouldDispatchFirstLayoutAfterFinishedParsing
&& frame
->document()->hasFinishedParsing()) {
1920 m_shouldDispatchFirstLayoutAfterFinishedParsing
= false;
1921 client()->didFirstLayoutAfterFinishedParsing();
1926 void WebViewImpl::paint(WebCanvas
* canvas
, const WebRect
& rect
)
1928 // This should only be used when compositing is not being used for this
1929 // WebView, and it is painting into the recording of its parent.
1930 ASSERT(!isAcceleratedCompositingActive());
1932 double paintStart
= currentTime();
1933 PageWidgetDelegate::paint(*m_page
, canvas
, rect
, *m_page
->deprecatedLocalMainFrame());
1934 double paintEnd
= currentTime();
1935 double pixelsPerSec
= (rect
.width
* rect
.height
) / (paintEnd
- paintStart
);
1936 Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintDurationMS", (paintEnd
- paintStart
) * 1000, 0, 120, 30);
1937 Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintMegapixPerSecond", pixelsPerSec
/ 1000000, 10, 210, 30);
1941 void WebViewImpl::paintCompositedDeprecated(WebCanvas
* canvas
, const WebRect
& rect
)
1943 // Note: This method exists on OS(ANDROID) and will hopefully be
1944 // removed once the link disambiguation feature renders using
1946 ASSERT(isAcceleratedCompositingActive());
1948 PageWidgetDelegate::paintIgnoringCompositing(*m_page
, canvas
, rect
, *m_page
->deprecatedLocalMainFrame());
1952 void WebViewImpl::layoutAndPaintAsync(WebLayoutAndPaintAsyncCallback
* callback
)
1954 m_layerTreeView
->layoutAndPaintAsync(callback
);
1957 void WebViewImpl::compositeAndReadbackAsync(WebCompositeAndReadbackAsyncCallback
* callback
)
1959 m_layerTreeView
->compositeAndReadbackAsync(callback
);
1962 void WebViewImpl::themeChanged()
1966 if (!page()->mainFrame()->isLocalFrame())
1968 FrameView
* view
= page()->deprecatedLocalMainFrame()->view();
1970 WebRect
damagedRect(0, 0, m_size
.width
, m_size
.height
);
1971 view
->invalidateRect(damagedRect
);
1974 void WebViewImpl::enterFullScreenForElement(Element
* element
)
1976 m_fullscreenController
->enterFullScreenForElement(element
);
1979 void WebViewImpl::exitFullScreenForElement(Element
* element
)
1981 m_fullscreenController
->exitFullScreenForElement(element
);
1984 void WebViewImpl::clearCompositedSelection()
1986 if (m_layerTreeView
)
1987 m_layerTreeView
->clearSelection();
1990 void WebViewImpl::updateCompositedSelection(const WebSelection
& selection
)
1992 if (m_layerTreeView
)
1993 m_layerTreeView
->registerSelection(selection
);
1996 bool WebViewImpl::hasHorizontalScrollbar()
1998 return mainFrameImpl()->frameView()->horizontalScrollbar();
2001 bool WebViewImpl::hasVerticalScrollbar()
2003 return mainFrameImpl()->frameView()->verticalScrollbar();
2006 const WebInputEvent
* WebViewImpl::m_currentInputEvent
= nullptr;
2008 // FIXME: autogenerate this kind of code, and use it throughout Blink rather than
2009 // the one-offs for subsets of these values.
2010 static String
inputTypeToName(WebInputEvent::Type type
)
2013 case WebInputEvent::MouseDown
:
2014 return EventTypeNames::mousedown
;
2015 case WebInputEvent::MouseUp
:
2016 return EventTypeNames::mouseup
;
2017 case WebInputEvent::MouseMove
:
2018 return EventTypeNames::mousemove
;
2019 case WebInputEvent::MouseEnter
:
2020 return EventTypeNames::mouseenter
;
2021 case WebInputEvent::MouseLeave
:
2022 return EventTypeNames::mouseleave
;
2023 case WebInputEvent::ContextMenu
:
2024 return EventTypeNames::contextmenu
;
2025 case WebInputEvent::MouseWheel
:
2026 return EventTypeNames::mousewheel
;
2027 case WebInputEvent::KeyDown
:
2028 return EventTypeNames::keydown
;
2029 case WebInputEvent::KeyUp
:
2030 return EventTypeNames::keyup
;
2031 case WebInputEvent::GestureScrollBegin
:
2032 return EventTypeNames::gesturescrollstart
;
2033 case WebInputEvent::GestureScrollEnd
:
2034 return EventTypeNames::gesturescrollend
;
2035 case WebInputEvent::GestureScrollUpdate
:
2036 return EventTypeNames::gesturescrollupdate
;
2037 case WebInputEvent::GestureTapDown
:
2038 return EventTypeNames::gesturetapdown
;
2039 case WebInputEvent::GestureShowPress
:
2040 return EventTypeNames::gestureshowpress
;
2041 case WebInputEvent::GestureTap
:
2042 return EventTypeNames::gesturetap
;
2043 case WebInputEvent::GestureTapUnconfirmed
:
2044 return EventTypeNames::gesturetapunconfirmed
;
2045 case WebInputEvent::TouchStart
:
2046 return EventTypeNames::touchstart
;
2047 case WebInputEvent::TouchMove
:
2048 return EventTypeNames::touchmove
;
2049 case WebInputEvent::TouchEnd
:
2050 return EventTypeNames::touchend
;
2051 case WebInputEvent::TouchCancel
:
2052 return EventTypeNames::touchcancel
;
2054 return String("unknown");
2058 bool WebViewImpl::handleInputEvent(const WebInputEvent
& inputEvent
)
2060 // TODO(dcheng): The fact that this is getting called when there is no local
2061 // main frame is problematic and probably indicates a bug in the input event
2063 if (!mainFrameImpl())
2066 WebAutofillClient
* autofillClient
= mainFrameImpl()->autofillClient();
2067 UserGestureNotifier
notifier(autofillClient
, &m_userGestureObserved
);
2068 // On the first input event since page load, |notifier| instructs the
2069 // autofill client to unblock values of password input fields of any forms
2070 // on the page. There is a single input event, GestureTap, which can both
2071 // be the first event after page load, and cause a form submission. In that
2072 // case, the form submission happens before the autofill client is told
2073 // to unblock the password values, and so the password values are not
2074 // submitted. To avoid that, GestureTap is handled explicitly:
2075 if (inputEvent
.type
== WebInputEvent::GestureTap
&& autofillClient
) {
2076 m_userGestureObserved
= true;
2077 autofillClient
->firstUserGestureObserved();
2080 TRACE_EVENT1("input", "WebViewImpl::handleInputEvent", "type", inputTypeToName(inputEvent
.type
).ascii());
2081 // If we've started a drag and drop operation, ignore input events until
2083 if (m_doingDragAndDrop
)
2086 if (m_devToolsEmulator
->handleInputEvent(inputEvent
))
2089 if (InspectorOverlayImpl
* overlay
= inspectorOverlay()) {
2090 if (overlay
->handleInputEvent(inputEvent
))
2094 // Report the event to be NOT processed by WebKit, so that the browser can handle it appropriately.
2095 if (m_ignoreInputEvents
)
2098 TemporaryChange
<const WebInputEvent
*> currentEventChange(m_currentInputEvent
, &inputEvent
);
2099 UIEventWithKeyState::clearNewTabModifierSetFromIsolatedWorld();
2101 if (isPointerLocked() && WebInputEvent::isMouseEventType(inputEvent
.type
)) {
2102 pointerLockMouseEvent(inputEvent
);
2106 if (m_mouseCaptureNode
&& WebInputEvent::isMouseEventType(inputEvent
.type
)) {
2107 TRACE_EVENT1("input", "captured mouse event", "type", inputEvent
.type
);
2108 // Save m_mouseCaptureNode since mouseCaptureLost() will clear it.
2109 RefPtrWillBeRawPtr
<Node
> node
= m_mouseCaptureNode
;
2111 // Not all platforms call mouseCaptureLost() directly.
2112 if (inputEvent
.type
== WebInputEvent::MouseUp
)
2115 OwnPtr
<UserGestureIndicator
> gestureIndicator
;
2117 AtomicString eventType
;
2118 switch (inputEvent
.type
) {
2119 case WebInputEvent::MouseMove
:
2120 eventType
= EventTypeNames::mousemove
;
2122 case WebInputEvent::MouseLeave
:
2123 eventType
= EventTypeNames::mouseout
;
2125 case WebInputEvent::MouseDown
:
2126 eventType
= EventTypeNames::mousedown
;
2127 gestureIndicator
= adoptPtr(new UserGestureIndicator(DefinitelyProcessingNewUserGesture
));
2128 m_mouseCaptureGestureToken
= gestureIndicator
->currentToken();
2130 case WebInputEvent::MouseUp
:
2131 eventType
= EventTypeNames::mouseup
;
2132 gestureIndicator
= adoptPtr(new UserGestureIndicator(m_mouseCaptureGestureToken
.release()));
2135 ASSERT_NOT_REACHED();
2138 node
->dispatchMouseEvent(
2139 PlatformMouseEventBuilder(mainFrameImpl()->frameView(), static_cast<const WebMouseEvent
&>(inputEvent
)),
2140 eventType
, static_cast<const WebMouseEvent
&>(inputEvent
).clickCount
);
2144 // FIXME: This should take in the intended frame, not the local frame root.
2145 if (PageWidgetDelegate::handleInputEvent(*this, inputEvent
, mainFrameImpl()->frame()))
2148 // Unhandled touchpad gesture pinch events synthesize mouse wheel events.
2149 if (inputEvent
.type
== WebInputEvent::GesturePinchUpdate
) {
2150 const WebGestureEvent
& pinchEvent
= static_cast<const WebGestureEvent
&>(inputEvent
);
2152 // First, synthesize a Windows-like wheel event to send to any handlers that may exist.
2153 if (handleSyntheticWheelFromTouchpadPinchEvent(pinchEvent
))
2156 if (pinchEvent
.data
.pinchUpdate
.zoomDisabled
)
2159 if (page()->frameHost().visualViewport().magnifyScaleAroundAnchor(pinchEvent
.data
.pinchUpdate
.scale
, FloatPoint(pinchEvent
.x
, pinchEvent
.y
)))
2166 void WebViewImpl::setCursorVisibilityState(bool isVisible
)
2169 m_page
->setIsCursorVisible(isVisible
);
2172 void WebViewImpl::mouseCaptureLost()
2174 TRACE_EVENT_ASYNC_END0("input", "capturing mouse", this);
2175 m_mouseCaptureNode
= nullptr;
2178 void WebViewImpl::setFocus(bool enable
)
2180 m_page
->focusController().setFocused(enable
);
2182 m_page
->focusController().setActive(true);
2183 RefPtrWillBeRawPtr
<Frame
> focusedFrame
= m_page
->focusController().focusedFrame();
2184 if (focusedFrame
&& focusedFrame
->isLocalFrame()) {
2185 LocalFrame
* localFrame
= toLocalFrame(focusedFrame
.get());
2186 Element
* element
= localFrame
->document()->focusedElement();
2187 if (element
&& localFrame
->selection().selection().isNone()) {
2188 // If the selection was cleared while the WebView was not
2189 // focused, then the focus element shows with a focus ring but
2190 // no caret and does respond to keyboard inputs.
2191 if (element
->isTextFormControl()) {
2192 element
->updateFocusAppearance(true);
2193 } else if (element
->isContentEditable()) {
2194 // updateFocusAppearance() selects all the text of
2195 // contentseditable DIVs. So we set the selection explicitly
2196 // instead. Note that this has the side effect of moving the
2197 // caret back to the beginning of the text.
2198 Position
position(element
, 0);
2199 localFrame
->selection().setSelection(VisibleSelection(position
, SEL_DEFAULT_AFFINITY
));
2203 m_imeAcceptEvents
= true;
2207 // Clear focus on the currently focused frame if any.
2211 LocalFrame
* frame
= m_page
->mainFrame() && m_page
->mainFrame()->isLocalFrame()
2212 ? m_page
->deprecatedLocalMainFrame() : 0;
2216 RefPtrWillBeRawPtr
<Frame
> focusedFrame
= m_page
->focusController().focusedFrame();
2217 if (focusedFrame
&& focusedFrame
->isLocalFrame()) {
2218 // Finish an ongoing composition to delete the composition node.
2219 if (toLocalFrame(focusedFrame
.get())->inputMethodController().hasComposition()) {
2220 WebAutofillClient
* autofillClient
= WebLocalFrameImpl::fromFrame(toLocalFrame(focusedFrame
.get()))->autofillClient();
2223 autofillClient
->setIgnoreTextChanges(true);
2225 toLocalFrame(focusedFrame
.get())->inputMethodController().confirmComposition();
2228 autofillClient
->setIgnoreTextChanges(false);
2230 m_imeAcceptEvents
= false;
2235 bool WebViewImpl::setComposition(
2236 const WebString
& text
,
2237 const WebVector
<WebCompositionUnderline
>& underlines
,
2241 LocalFrame
* focused
= toLocalFrame(focusedCoreFrame());
2242 if (!focused
|| !m_imeAcceptEvents
)
2245 if (WebPlugin
* plugin
= focusedPluginIfInputMethodSupported(focused
))
2246 return plugin
->setComposition(text
, underlines
, selectionStart
, selectionEnd
);
2248 // The input focus has been moved to another WebWidget object.
2249 // We should use this |editor| object only to complete the ongoing
2251 InputMethodController
& inputMethodController
= focused
->inputMethodController();
2252 if (!focused
->editor().canEdit() && !inputMethodController
.hasComposition())
2255 // We should verify the parent node of this IME composition node are
2256 // editable because JavaScript may delete a parent node of the composition
2257 // node. In this case, WebKit crashes while deleting texts from the parent
2258 // node, which doesn't exist any longer.
2259 const EphemeralRange range
= inputMethodController
.compositionEphemeralRange();
2260 if (range
.isNotNull()) {
2261 Node
* node
= range
.startPosition().computeContainerNode();
2262 if (!node
|| !node
->isContentEditable())
2266 // A keypress event is canceled. If an ongoing composition exists, then the
2267 // keydown event should have arisen from a handled key (e.g., backspace).
2268 // In this case we ignore the cancellation and continue; otherwise (no
2269 // ongoing composition) we exit and signal success only for attempts to
2270 // clear the composition.
2271 if (m_suppressNextKeypressEvent
&& !inputMethodController
.hasComposition())
2272 return text
.isEmpty();
2274 UserGestureIndicator
gestureIndicator(DefinitelyProcessingNewUserGesture
);
2276 // When the range of composition underlines overlap with the range between
2277 // selectionStart and selectionEnd, WebKit somehow won't paint the selection
2278 // at all (see InlineTextBox::paint() function in InlineTextBox.cpp).
2279 // But the selection range actually takes effect.
2280 inputMethodController
.setComposition(String(text
),
2281 CompositionUnderlineVectorBuilder(underlines
),
2282 selectionStart
, selectionEnd
);
2284 return text
.isEmpty() || inputMethodController
.hasComposition();
2287 bool WebViewImpl::confirmComposition()
2289 return confirmComposition(DoNotKeepSelection
);
2292 bool WebViewImpl::confirmComposition(ConfirmCompositionBehavior selectionBehavior
)
2294 return confirmComposition(WebString(), selectionBehavior
);
2297 bool WebViewImpl::confirmComposition(const WebString
& text
)
2299 return confirmComposition(text
, DoNotKeepSelection
);
2302 bool WebViewImpl::confirmComposition(const WebString
& text
, ConfirmCompositionBehavior selectionBehavior
)
2304 LocalFrame
* focused
= toLocalFrame(focusedCoreFrame());
2305 if (!focused
|| !m_imeAcceptEvents
)
2308 if (WebPlugin
* plugin
= focusedPluginIfInputMethodSupported(focused
))
2309 return plugin
->confirmComposition(text
, selectionBehavior
);
2311 return focused
->inputMethodController().confirmCompositionOrInsertText(text
, selectionBehavior
== KeepSelection
? InputMethodController::KeepSelection
: InputMethodController::DoNotKeepSelection
);
2314 bool WebViewImpl::compositionRange(size_t* location
, size_t* length
)
2316 // FIXME: Long term, the focused frame should be a local frame. For now,
2317 // return early to avoid crashes.
2318 Frame
* frame
= focusedCoreFrame();
2319 if (!frame
|| frame
->isRemoteFrame())
2322 LocalFrame
* focused
= toLocalFrame(frame
);
2323 if (!focused
|| !m_imeAcceptEvents
)
2326 const EphemeralRange range
= focused
->inputMethodController().compositionEphemeralRange();
2330 Element
* editable
= focused
->selection().rootEditableElementOrDocumentElement();
2332 PlainTextRange
plainTextRange(PlainTextRange::create(*editable
, range
));
2333 if (plainTextRange
.isNull())
2335 *location
= plainTextRange
.start();
2336 *length
= plainTextRange
.length();
2340 WebTextInputInfo
WebViewImpl::textInputInfo()
2342 WebTextInputInfo info
;
2344 Frame
* focusedFrame
= focusedCoreFrame();
2345 if (!focusedFrame
->isLocalFrame())
2348 LocalFrame
* focused
= toLocalFrame(focusedFrame
);
2352 FrameSelection
& selection
= focused
->selection();
2353 Element
* element
= selection
.selection().rootEditableElement();
2357 info
.inputMode
= inputModeOfFocusedElement();
2359 info
.type
= textInputType();
2360 info
.flags
= textInputFlags();
2361 if (info
.type
== WebTextInputTypeNone
)
2364 if (!focused
->editor().canEdit())
2367 // Emits an object replacement character for each replaced element so that
2368 // it is exposed to IME and thus could be deleted by IME on android.
2369 info
.value
= plainText(EphemeralRange::rangeOfContents(*element
), TextIteratorEmitsObjectReplacementCharacter
);
2371 if (info
.value
.isEmpty())
2374 EphemeralRange firstRange
= firstEphemeralRangeOf(selection
.selection());
2375 if (firstRange
.isNotNull()) {
2376 PlainTextRange
plainTextRange(PlainTextRange::create(*element
, firstRange
));
2377 if (plainTextRange
.isNotNull()) {
2378 info
.selectionStart
= plainTextRange
.start();
2379 info
.selectionEnd
= plainTextRange
.end();
2383 EphemeralRange range
= focused
->inputMethodController().compositionEphemeralRange();
2384 if (range
.isNotNull()) {
2385 PlainTextRange
plainTextRange(PlainTextRange::create(*element
, range
));
2386 if (plainTextRange
.isNotNull()) {
2387 info
.compositionStart
= plainTextRange
.start();
2388 info
.compositionEnd
= plainTextRange
.end();
2395 WebTextInputType
WebViewImpl::textInputType()
2397 Element
* element
= focusedElement();
2399 return WebTextInputTypeNone
;
2401 if (isHTMLInputElement(*element
)) {
2402 HTMLInputElement
& input
= toHTMLInputElement(*element
);
2403 const AtomicString
& type
= input
.type();
2405 if (input
.isDisabledOrReadOnly())
2406 return WebTextInputTypeNone
;
2408 if (type
== InputTypeNames::password
)
2409 return WebTextInputTypePassword
;
2410 if (type
== InputTypeNames::search
)
2411 return WebTextInputTypeSearch
;
2412 if (type
== InputTypeNames::email
)
2413 return WebTextInputTypeEmail
;
2414 if (type
== InputTypeNames::number
)
2415 return WebTextInputTypeNumber
;
2416 if (type
== InputTypeNames::tel
)
2417 return WebTextInputTypeTelephone
;
2418 if (type
== InputTypeNames::url
)
2419 return WebTextInputTypeURL
;
2420 if (type
== InputTypeNames::date
)
2421 return WebTextInputTypeDate
;
2422 if (type
== InputTypeNames::datetime_local
)
2423 return WebTextInputTypeDateTimeLocal
;
2424 if (type
== InputTypeNames::month
)
2425 return WebTextInputTypeMonth
;
2426 if (type
== InputTypeNames::time
)
2427 return WebTextInputTypeTime
;
2428 if (type
== InputTypeNames::week
)
2429 return WebTextInputTypeWeek
;
2430 if (type
== InputTypeNames::text
)
2431 return WebTextInputTypeText
;
2433 return WebTextInputTypeNone
;
2436 if (isHTMLTextAreaElement(*element
)) {
2437 if (toHTMLTextAreaElement(*element
).isDisabledOrReadOnly())
2438 return WebTextInputTypeNone
;
2439 return WebTextInputTypeTextArea
;
2442 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
2443 if (element
->isHTMLElement()) {
2444 if (toHTMLElement(element
)->isDateTimeFieldElement())
2445 return WebTextInputTypeDateTimeField
;
2449 if (element
->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable
))
2450 return WebTextInputTypeContentEditable
;
2452 return WebTextInputTypeNone
;
2455 int WebViewImpl::textInputFlags()
2457 Element
* element
= focusedElement();
2459 return WebTextInputFlagNone
;
2461 DEFINE_STATIC_LOCAL(AtomicString
, autocompleteString
, ("autocomplete", AtomicString::ConstructFromLiteral
));
2462 DEFINE_STATIC_LOCAL(AtomicString
, autocorrectString
, ("autocorrect", AtomicString::ConstructFromLiteral
));
2465 const AtomicString
& autocomplete
= element
->getAttribute(autocompleteString
);
2466 if (autocomplete
== "on")
2467 flags
|= WebTextInputFlagAutocompleteOn
;
2468 else if (autocomplete
== "off")
2469 flags
|= WebTextInputFlagAutocompleteOff
;
2471 const AtomicString
& autocorrect
= element
->getAttribute(autocorrectString
);
2472 if (autocorrect
== "on")
2473 flags
|= WebTextInputFlagAutocorrectOn
;
2474 else if (autocorrect
== "off")
2475 flags
|= WebTextInputFlagAutocorrectOff
;
2477 SpellcheckAttributeState spellcheck
= element
->spellcheckAttributeState();
2478 if (spellcheck
== SpellcheckAttributeTrue
)
2479 flags
|= WebTextInputFlagSpellcheckOn
;
2480 else if (spellcheck
== SpellcheckAttributeFalse
)
2481 flags
|= WebTextInputFlagSpellcheckOff
;
2483 if (isHTMLTextFormControlElement(element
)) {
2484 HTMLTextFormControlElement
* formElement
= static_cast<HTMLTextFormControlElement
*>(element
);
2485 if (formElement
->supportsAutocapitalize()) {
2486 DEFINE_STATIC_LOCAL(const AtomicString
, none
, ("none", AtomicString::ConstructFromLiteral
));
2487 DEFINE_STATIC_LOCAL(const AtomicString
, characters
, ("characters", AtomicString::ConstructFromLiteral
));
2488 DEFINE_STATIC_LOCAL(const AtomicString
, words
, ("words", AtomicString::ConstructFromLiteral
));
2489 DEFINE_STATIC_LOCAL(const AtomicString
, sentences
, ("sentences", AtomicString::ConstructFromLiteral
));
2491 const AtomicString
& autocapitalize
= formElement
->autocapitalize();
2492 if (autocapitalize
== none
)
2493 flags
|= WebTextInputFlagAutocapitalizeNone
;
2494 else if (autocapitalize
== characters
)
2495 flags
|= WebTextInputFlagAutocapitalizeCharacters
;
2496 else if (autocapitalize
== words
)
2497 flags
|= WebTextInputFlagAutocapitalizeWords
;
2498 else if (autocapitalize
== sentences
)
2499 flags
|= WebTextInputFlagAutocapitalizeSentences
;
2501 ASSERT_NOT_REACHED();
2508 WebString
WebViewImpl::inputModeOfFocusedElement()
2510 if (!RuntimeEnabledFeatures::inputModeAttributeEnabled())
2513 Element
* element
= focusedElement();
2517 if (isHTMLInputElement(*element
)) {
2518 const HTMLInputElement
& input
= toHTMLInputElement(*element
);
2519 if (input
.supportsInputModeAttribute())
2520 return input
.fastGetAttribute(HTMLNames::inputmodeAttr
).lower();
2523 if (isHTMLTextAreaElement(*element
)) {
2524 const HTMLTextAreaElement
& textarea
= toHTMLTextAreaElement(*element
);
2525 return textarea
.fastGetAttribute(HTMLNames::inputmodeAttr
).lower();
2531 bool WebViewImpl::selectionBounds(WebRect
& anchor
, WebRect
& focus
) const
2533 const Frame
* frame
= focusedCoreFrame();
2534 if (!frame
|| !frame
->isLocalFrame())
2537 const LocalFrame
* localFrame
= toLocalFrame(frame
);
2540 FrameSelection
& selection
= localFrame
->selection();
2542 if (selection
.isCaret()) {
2543 anchor
= focus
= selection
.absoluteCaretBounds();
2545 const EphemeralRange selectedRange
= selection
.selection().toNormalizedEphemeralRange();
2546 if (selectedRange
.isNull())
2548 anchor
= localFrame
->editor().firstRectForRange(EphemeralRange(selectedRange
.startPosition()));
2549 focus
= localFrame
->editor().firstRectForRange(EphemeralRange(selectedRange
.endPosition()));
2552 anchor
= localFrame
->view()->contentsToViewport(anchor
);
2553 focus
= localFrame
->view()->contentsToViewport(focus
);
2555 if (!selection
.selection().isBaseFirst())
2556 std::swap(anchor
, focus
);
2560 WebPlugin
* WebViewImpl::focusedPluginIfInputMethodSupported(LocalFrame
* frame
)
2562 WebPluginContainerImpl
* container
= WebLocalFrameImpl::pluginContainerFromNode(frame
, WebNode(focusedElement()));
2563 if (container
&& container
->supportsInputMethod())
2564 return container
->plugin();
2568 bool WebViewImpl::selectionTextDirection(WebTextDirection
& start
, WebTextDirection
& end
) const
2570 const Frame
* frame
= focusedCoreFrame();
2571 if (!frame
|| frame
->isRemoteFrame())
2573 FrameSelection
& selection
= toLocalFrame(frame
)->selection();
2574 if (selection
.selection().toNormalizedEphemeralRange().isNull())
2576 start
= toWebTextDirection(primaryDirectionOf(*selection
.start().anchorNode()));
2577 end
= toWebTextDirection(primaryDirectionOf(*selection
.end().anchorNode()));
2581 bool WebViewImpl::isSelectionAnchorFirst() const
2583 const Frame
* frame
= focusedCoreFrame();
2584 if (!frame
|| frame
->isRemoteFrame())
2586 return toLocalFrame(frame
)->selection().selection().isBaseFirst();
2589 WebColor
WebViewImpl::backgroundColor() const
2591 if (isTransparent())
2592 return Color::transparent
;
2594 return m_baseBackgroundColor
;
2595 if (!m_page
->mainFrame())
2596 return m_baseBackgroundColor
;
2597 if (!m_page
->mainFrame()->isLocalFrame())
2598 return m_baseBackgroundColor
;
2599 FrameView
* view
= m_page
->deprecatedLocalMainFrame()->view();
2600 return view
->documentBackgroundColor().rgb();
2603 WebPagePopup
* WebViewImpl::pagePopup() const
2605 return m_pagePopup
.get();
2608 bool WebViewImpl::caretOrSelectionRange(size_t* location
, size_t* length
)
2610 const LocalFrame
* focused
= toLocalFrame(focusedCoreFrame());
2614 PlainTextRange selectionOffsets
= focused
->inputMethodController().getSelectionOffsets();
2615 if (selectionOffsets
.isNull())
2618 *location
= selectionOffsets
.start();
2619 *length
= selectionOffsets
.length();
2623 void WebViewImpl::setTextDirection(WebTextDirection direction
)
2625 // The Editor::setBaseWritingDirection() function checks if we can change
2626 // the text direction of the selected node and updates its DOM "dir"
2627 // attribute and its CSS "direction" property.
2628 // So, we just call the function as Safari does.
2629 const LocalFrame
* focused
= toLocalFrame(focusedCoreFrame());
2633 Editor
& editor
= focused
->editor();
2634 if (!editor
.canEdit())
2637 switch (direction
) {
2638 case WebTextDirectionDefault
:
2639 editor
.setBaseWritingDirection(NaturalWritingDirection
);
2642 case WebTextDirectionLeftToRight
:
2643 editor
.setBaseWritingDirection(LeftToRightWritingDirection
);
2646 case WebTextDirectionRightToLeft
:
2647 editor
.setBaseWritingDirection(RightToLeftWritingDirection
);
2656 bool WebViewImpl::isAcceleratedCompositingActive() const
2661 void WebViewImpl::willCloseLayerTreeView()
2663 if (m_linkHighlightsTimeline
) {
2664 detachCompositorAnimationTimeline(m_linkHighlightsTimeline
.get());
2665 m_linkHighlightsTimeline
.clear();
2668 setRootGraphicsLayer(nullptr);
2669 m_layerTreeView
= 0;
2672 void WebViewImpl::didAcquirePointerLock()
2675 page()->pointerLockController().didAcquirePointerLock();
2678 void WebViewImpl::didNotAcquirePointerLock()
2681 page()->pointerLockController().didNotAcquirePointerLock();
2684 void WebViewImpl::didLosePointerLock()
2686 m_pointerLockGestureToken
.clear();
2688 page()->pointerLockController().didLosePointerLock();
2691 void WebViewImpl::didChangeWindowResizerRect()
2693 if (mainFrameImpl()->frameView())
2694 mainFrameImpl()->frameView()->windowResizerRectChanged();
2697 // WebView --------------------------------------------------------------------
2699 WebSettingsImpl
* WebViewImpl::settingsImpl()
2702 m_webSettings
= adoptPtr(new WebSettingsImpl(&m_page
->settings(), m_devToolsEmulator
.get()));
2703 ASSERT(m_webSettings
);
2704 return m_webSettings
.get();
2707 WebSettings
* WebViewImpl::settings()
2709 return settingsImpl();
2712 WebString
WebViewImpl::pageEncoding() const
2717 if (!m_page
->mainFrame()->isLocalFrame())
2720 // FIXME: Is this check needed?
2721 if (!m_page
->deprecatedLocalMainFrame()->document()->loader())
2724 return m_page
->deprecatedLocalMainFrame()->document()->encodingName();
2727 void WebViewImpl::setPageEncoding(const WebString
& encodingName
)
2732 // Only change override encoding, don't change default encoding.
2733 // Note that the new encoding must be 0 if it isn't supposed to be set.
2734 AtomicString newEncodingName
;
2735 if (!encodingName
.isEmpty())
2736 newEncodingName
= encodingName
;
2737 m_page
->frameHost().setOverrideEncoding(newEncodingName
);
2739 if (m_page
->mainFrame()->isLocalFrame()) {
2740 if (!m_page
->deprecatedLocalMainFrame()->loader().currentItem())
2742 FrameLoadRequest request
= FrameLoadRequest(
2744 m_page
->deprecatedLocalMainFrame()->loader().resourceRequestForReload(
2745 FrameLoadTypeReload
, KURL(), ClientRedirect
));
2746 request
.setClientRedirect(ClientRedirect
);
2747 m_page
->deprecatedLocalMainFrame()->loader().load(request
, FrameLoadTypeReload
);
2751 WebFrame
* WebViewImpl::mainFrame()
2753 return WebFrame::fromFrame(m_page
? m_page
->mainFrame() : 0);
2756 WebFrame
* WebViewImpl::findFrameByName(
2757 const WebString
& name
, WebFrame
* relativeToFrame
)
2759 // FIXME: Either this should only deal with WebLocalFrames or it should move to WebFrame.
2760 if (!relativeToFrame
)
2761 relativeToFrame
= mainFrame();
2762 Frame
* frame
= toWebLocalFrameImpl(relativeToFrame
)->frame();
2763 frame
= frame
->tree().find(name
);
2764 if (!frame
|| !frame
->isLocalFrame())
2766 return WebLocalFrameImpl::fromFrame(toLocalFrame(frame
));
2769 WebFrame
* WebViewImpl::focusedFrame()
2771 return WebFrame::fromFrame(focusedCoreFrame());
2774 void WebViewImpl::setFocusedFrame(WebFrame
* frame
)
2777 // Clears the focused frame if any.
2778 Frame
* focusedFrame
= focusedCoreFrame();
2779 if (focusedFrame
&& focusedFrame
->isLocalFrame())
2780 toLocalFrame(focusedFrame
)->selection().setFocused(false);
2783 LocalFrame
* coreFrame
= toWebLocalFrameImpl(frame
)->frame();
2784 coreFrame
->page()->focusController().setFocusedFrame(coreFrame
);
2787 void WebViewImpl::setInitialFocus(bool reverse
)
2791 Frame
* frame
= page()->focusController().focusedOrMainFrame();
2792 if (frame
->isLocalFrame()) {
2793 if (Document
* document
= toLocalFrame(frame
)->document())
2794 document
->setFocusedElement(nullptr);
2796 page()->focusController().setInitialFocus(reverse
? WebFocusTypeBackward
: WebFocusTypeForward
);
2799 void WebViewImpl::clearFocusedElement()
2801 RefPtrWillBeRawPtr
<Frame
> frame
= focusedCoreFrame();
2802 if (!frame
|| !frame
->isLocalFrame())
2805 LocalFrame
* localFrame
= toLocalFrame(frame
.get());
2807 RefPtrWillBeRawPtr
<Document
> document
= localFrame
->document();
2811 RefPtrWillBeRawPtr
<Element
> oldFocusedElement
= document
->focusedElement();
2813 // Clear the focused node.
2814 document
->setFocusedElement(nullptr);
2816 if (!oldFocusedElement
)
2819 // If a text field has focus, we need to make sure the selection controller
2820 // knows to remove selection from it. Otherwise, the text field is still
2821 // processing keyboard events even though focus has been moved to the page and
2822 // keystrokes get eaten as a result.
2823 if (oldFocusedElement
->isContentEditable() || oldFocusedElement
->isTextFormControl())
2824 localFrame
->selection().clear();
2827 bool WebViewImpl::scrollFocusedNodeIntoRect(const WebRect
& rectInViewport
)
2829 LocalFrame
* frame
= page()->mainFrame() && page()->mainFrame()->isLocalFrame()
2830 ? page()->deprecatedLocalMainFrame() : 0;
2831 Element
* element
= focusedElement();
2832 if (!frame
|| !frame
->view() || !element
)
2835 element
->document().updateLayoutIgnorePendingStylesheets();
2837 bool zoomInToLegibleScale
= m_webSettings
->autoZoomFocusedNodeToLegibleScale()
2838 && !shouldDisableDesktopWorkarounds();
2840 if (zoomInToLegibleScale
) {
2841 // When deciding whether to zoom in on a focused text box, we should decide not to
2842 // zoom in if the user won't be able to zoom out. e.g if the textbox is within a
2843 // touch-action: none container the user can't zoom back out.
2844 TouchAction action
= TouchActionUtil::computeEffectiveTouchAction(*element
);
2845 if (action
!= TouchActionAuto
&& !(action
& TouchActionPinchZoom
))
2846 zoomInToLegibleScale
= false;
2852 computeScaleAndScrollForFocusedNode(element
, zoomInToLegibleScale
, scale
, scroll
, needAnimation
);
2854 return startPageScaleAnimation(scroll
, false, scale
, scrollAndScaleAnimationDurationInSeconds
);
2859 void WebViewImpl::smoothScroll(int targetX
, int targetY
, long durationMs
)
2861 IntPoint
targetPosition(targetX
, targetY
);
2862 startPageScaleAnimation(targetPosition
, false, pageScaleFactor(), (double)durationMs
/ 1000);
2865 void WebViewImpl::computeScaleAndScrollForFocusedNode(Node
* focusedNode
, bool zoomInToLegibleScale
, float& newScale
, IntPoint
& newScroll
, bool& needAnimation
)
2867 VisualViewport
& visualViewport
= page()->frameHost().visualViewport();
2869 WebRect caretInViewport
, unusedEnd
;
2870 selectionBounds(caretInViewport
, unusedEnd
);
2872 // 'caretInDocument' is rect encompassing the blinking cursor relative to the root document.
2873 IntRect caretInDocument
= mainFrameImpl()->frameView()->frameToContents(visualViewport
.viewportToRootFrame(caretInViewport
));
2874 IntRect textboxRectInDocument
= mainFrameImpl()->frameView()->frameToContents(
2875 focusedNode
->document().view()->contentsToRootFrame(pixelSnappedIntRect(focusedNode
->Node::boundingBox())));
2877 if (!zoomInToLegibleScale
) {
2878 newScale
= pageScaleFactor();
2880 // Pick a scale which is reasonably readable. This is the scale at which
2881 // the caret height will become minReadableCaretHeightForNode (adjusted
2882 // for dpi and font scale factor).
2883 const int minReadableCaretHeightForNode
= textboxRectInDocument
.height() >= 2 * caretInDocument
.height() ? minReadableCaretHeightForTextArea
: minReadableCaretHeight
;
2884 newScale
= clampPageScaleFactorToLimits(maximumLegiblePageScale() * minReadableCaretHeightForNode
/ caretInDocument
.height());
2885 newScale
= std::max(newScale
, pageScaleFactor());
2887 const float deltaScale
= newScale
/ pageScaleFactor();
2889 needAnimation
= false;
2891 // If we are at less than the target zoom level, zoom in.
2892 if (deltaScale
> minScaleChangeToTriggerZoom
)
2893 needAnimation
= true;
2895 newScale
= pageScaleFactor();
2897 // If the caret is offscreen, then animate.
2898 if (!visualViewport
.visibleRectInDocument().contains(caretInDocument
))
2899 needAnimation
= true;
2901 // If the box is partially offscreen and it's possible to bring it fully
2902 // onscreen, then animate.
2903 if (visualViewport
.visibleRect().width() >= textboxRectInDocument
.width()
2904 && visualViewport
.visibleRect().height() >= textboxRectInDocument
.height()
2905 && !visualViewport
.visibleRectInDocument().contains(textboxRectInDocument
))
2906 needAnimation
= true;
2911 FloatSize targetViewportSize
= visualViewport
.size();
2912 targetViewportSize
.scale(1 / newScale
);
2914 if (textboxRectInDocument
.width() <= targetViewportSize
.width()) {
2915 // Field is narrower than screen. Try to leave padding on left so field's
2916 // label is visible, but it's more important to ensure entire field is
2918 int idealLeftPadding
= targetViewportSize
.width() * leftBoxRatio
;
2919 int maxLeftPaddingKeepingBoxOnscreen
= targetViewportSize
.width() - textboxRectInDocument
.width();
2920 newScroll
.setX(textboxRectInDocument
.x() - std::min
<int>(idealLeftPadding
, maxLeftPaddingKeepingBoxOnscreen
));
2922 // Field is wider than screen. Try to left-align field, unless caret would
2923 // be offscreen, in which case right-align the caret.
2924 newScroll
.setX(std::max
<int>(textboxRectInDocument
.x(), caretInDocument
.x() + caretInDocument
.width() + caretPadding
- targetViewportSize
.width()));
2926 if (textboxRectInDocument
.height() <= targetViewportSize
.height()) {
2927 // Field is shorter than screen. Vertically center it.
2928 newScroll
.setY(textboxRectInDocument
.y() - (targetViewportSize
.height() - textboxRectInDocument
.height()) / 2);
2930 // Field is taller than screen. Try to top align field, unless caret would
2931 // be offscreen, in which case bottom-align the caret.
2932 newScroll
.setY(std::max
<int>(textboxRectInDocument
.y(), caretInDocument
.y() + caretInDocument
.height() + caretPadding
- targetViewportSize
.height()));
2936 void WebViewImpl::advanceFocus(bool reverse
)
2938 page()->focusController().advanceFocus(reverse
? WebFocusTypeBackward
: WebFocusTypeForward
);
2941 double WebViewImpl::zoomLevel()
2946 double WebViewImpl::setZoomLevel(double zoomLevel
)
2948 if (zoomLevel
< m_minimumZoomLevel
)
2949 m_zoomLevel
= m_minimumZoomLevel
;
2950 else if (zoomLevel
> m_maximumZoomLevel
)
2951 m_zoomLevel
= m_maximumZoomLevel
;
2953 m_zoomLevel
= zoomLevel
;
2955 LocalFrame
* frame
= mainFrameImpl()->frame();
2956 if (!WebLocalFrameImpl::pluginContainerFromFrame(frame
)) {
2957 float zoomFactor
= m_zoomFactorOverride
? m_zoomFactorOverride
: static_cast<float>(zoomLevelToZoomFactor(m_zoomLevel
));
2958 frame
->setPageZoomFactor(zoomFactor
);
2964 void WebViewImpl::zoomLimitsChanged(double minimumZoomLevel
,
2965 double maximumZoomLevel
)
2967 m_minimumZoomLevel
= minimumZoomLevel
;
2968 m_maximumZoomLevel
= maximumZoomLevel
;
2969 m_client
->zoomLimitsChanged(m_minimumZoomLevel
, m_maximumZoomLevel
);
2972 float WebViewImpl::textZoomFactor()
2974 return mainFrameImpl()->frame()->textZoomFactor();
2977 float WebViewImpl::setTextZoomFactor(float textZoomFactor
)
2979 LocalFrame
* frame
= mainFrameImpl()->frame();
2980 if (WebLocalFrameImpl::pluginContainerFromFrame(frame
))
2983 frame
->setTextZoomFactor(textZoomFactor
);
2985 return textZoomFactor
;
2988 double WebView::zoomLevelToZoomFactor(double zoomLevel
)
2990 return pow(textSizeMultiplierRatio
, zoomLevel
);
2993 double WebView::zoomFactorToZoomLevel(double factor
)
2995 // Since factor = 1.2^level, level = log(factor) / log(1.2)
2996 return log(factor
) / log(textSizeMultiplierRatio
);
2999 float WebViewImpl::pageScaleFactor() const
3004 return page()->frameHost().visualViewport().scale();
3007 float WebViewImpl::clampPageScaleFactorToLimits(float scaleFactor
) const
3009 return pageScaleConstraintsSet().finalConstraints().clampToConstraints(scaleFactor
);
3012 void WebViewImpl::setVisualViewportOffset(const WebFloatPoint
& offset
)
3015 page()->frameHost().visualViewport().setLocation(offset
);
3018 void WebViewImpl::setPinchViewportOffset(const WebFloatPoint
& offset
)
3020 setVisualViewportOffset(offset
);
3023 WebFloatPoint
WebViewImpl::visualViewportOffset() const
3026 return page()->frameHost().visualViewport().visibleRect().location();
3029 WebFloatPoint
WebViewImpl::pinchViewportOffset() const
3031 return visualViewportOffset();
3034 void WebViewImpl::scrollAndRescaleViewports(float scaleFactor
,
3035 const IntPoint
& mainFrameOrigin
,
3036 const FloatPoint
& visualViewportOrigin
)
3041 if (!mainFrameImpl())
3044 FrameView
* view
= mainFrameImpl()->frameView();
3048 // Order is important: visual viewport location is clamped based on
3049 // main frame scroll position and visual viewport scale.
3051 view
->setScrollPosition(mainFrameOrigin
, ProgrammaticScroll
);
3053 setPageScaleFactor(scaleFactor
);
3055 page()->frameHost().visualViewport().setLocation(visualViewportOrigin
);
3058 void WebViewImpl::setPageScaleFactorAndLocation(float scaleFactor
, const FloatPoint
& location
)
3062 page()->frameHost().visualViewport().setScaleAndLocation(
3063 clampPageScaleFactorToLimits(scaleFactor
),
3067 void WebViewImpl::setPageScaleFactor(float scaleFactor
)
3071 scaleFactor
= clampPageScaleFactorToLimits(scaleFactor
);
3072 if (scaleFactor
== pageScaleFactor())
3075 page()->frameHost().visualViewport().setScale(scaleFactor
);
3078 float WebViewImpl::deviceScaleFactor() const
3083 return page()->deviceScaleFactor();
3086 void WebViewImpl::setDeviceScaleFactor(float scaleFactor
)
3091 page()->setDeviceScaleFactor(scaleFactor
);
3093 if (m_layerTreeView
)
3094 updateLayerTreeDeviceScaleFactor();
3097 void WebViewImpl::setDeviceColorProfile(const WebVector
<char>& colorProfile
)
3102 Vector
<char> deviceProfile
;
3103 deviceProfile
.append(colorProfile
.data(), colorProfile
.size());
3105 page()->setDeviceColorProfile(deviceProfile
);
3108 void WebViewImpl::resetDeviceColorProfile()
3113 page()->resetDeviceColorProfile();
3116 void WebViewImpl::enableAutoResizeMode(const WebSize
& minSize
, const WebSize
& maxSize
)
3118 m_shouldAutoResize
= true;
3119 m_minAutoSize
= minSize
;
3120 m_maxAutoSize
= maxSize
;
3121 configureAutoResizeMode();
3124 void WebViewImpl::disableAutoResizeMode()
3126 m_shouldAutoResize
= false;
3127 configureAutoResizeMode();
3130 void WebViewImpl::setDefaultPageScaleLimits(float minScale
, float maxScale
)
3132 return page()->frameHost().setDefaultPageScaleLimits(minScale
, maxScale
);
3135 void WebViewImpl::setInitialPageScaleOverride(float initialPageScaleFactorOverride
)
3137 PageScaleConstraints constraints
= pageScaleConstraintsSet().userAgentConstraints();
3138 constraints
.initialScale
= initialPageScaleFactorOverride
;
3140 if (constraints
== pageScaleConstraintsSet().userAgentConstraints())
3143 pageScaleConstraintsSet().setNeedsReset(true);
3144 page()->frameHost().setUserAgentPageScaleConstraints(constraints
);
3147 void WebViewImpl::setMaximumLegibleScale(float maximumLegibleScale
)
3149 m_maximumLegibleScale
= maximumLegibleScale
;
3152 void WebViewImpl::setIgnoreViewportTagScaleLimits(bool ignore
)
3154 PageScaleConstraints constraints
= pageScaleConstraintsSet().userAgentConstraints();
3156 constraints
.minimumScale
= pageScaleConstraintsSet().defaultConstraints().minimumScale
;
3157 constraints
.maximumScale
= pageScaleConstraintsSet().defaultConstraints().maximumScale
;
3159 constraints
.minimumScale
= -1;
3160 constraints
.maximumScale
= -1;
3162 page()->frameHost().setUserAgentPageScaleConstraints(constraints
);
3165 IntSize
WebViewImpl::mainFrameSize()
3167 return pageScaleConstraintsSet().mainFrameSize();
3170 PageScaleConstraintsSet
& WebViewImpl::pageScaleConstraintsSet() const
3172 return page()->frameHost().pageScaleConstraintsSet();
3175 void WebViewImpl::refreshPageScaleFactorAfterLayout()
3177 if (!mainFrame() || !page() || !page()->mainFrame() || !page()->mainFrame()->isLocalFrame() || !page()->deprecatedLocalMainFrame()->view())
3179 FrameView
* view
= page()->deprecatedLocalMainFrame()->view();
3181 updatePageDefinedViewportConstraints(mainFrameImpl()->frame()->document()->viewportDescription());
3182 pageScaleConstraintsSet().computeFinalConstraints();
3184 int verticalScrollbarWidth
= 0;
3185 if (view
->verticalScrollbar() && !view
->verticalScrollbar()->isOverlayScrollbar())
3186 verticalScrollbarWidth
= view
->verticalScrollbar()->width();
3187 pageScaleConstraintsSet().adjustFinalConstraintsToContentsSize(contentsSize(), verticalScrollbarWidth
, settings()->shrinksViewportContentToFit());
3189 float newPageScaleFactor
= pageScaleFactor();
3190 if (pageScaleConstraintsSet().needsReset() && pageScaleConstraintsSet().finalConstraints().initialScale
!= -1) {
3191 newPageScaleFactor
= pageScaleConstraintsSet().finalConstraints().initialScale
;
3192 pageScaleConstraintsSet().setNeedsReset(false);
3194 setPageScaleFactor(newPageScaleFactor
);
3196 updateLayerTreeViewport();
3199 void WebViewImpl::updatePageDefinedViewportConstraints(const ViewportDescription
& description
)
3201 // If we're not reading the viewport meta tag, allow GPU rasterization.
3202 if (!settingsImpl()->viewportMetaEnabled()) {
3203 m_matchesHeuristicsForGpuRasterization
= true;
3204 if (m_layerTreeView
)
3205 m_layerTreeView
->heuristicsForGpuRasterizationUpdated(m_matchesHeuristicsForGpuRasterization
);
3208 if (!settings()->viewportEnabled() || !page() || (!m_size
.width
&& !m_size
.height
) || !page()->mainFrame()->isLocalFrame())
3211 Document
* document
= page()->deprecatedLocalMainFrame()->document();
3213 m_matchesHeuristicsForGpuRasterization
= description
.matchesHeuristicsForGpuRasterization();
3214 if (m_layerTreeView
)
3215 m_layerTreeView
->heuristicsForGpuRasterizationUpdated(m_matchesHeuristicsForGpuRasterization
);
3217 Length defaultMinWidth
= document
->viewportDefaultMinWidth();
3218 if (defaultMinWidth
.isAuto())
3219 defaultMinWidth
= Length(ExtendToZoom
);
3221 ViewportDescription adjustedDescription
= description
;
3222 if (settingsImpl()->viewportMetaLayoutSizeQuirk() && adjustedDescription
.type
== ViewportDescription::ViewportMeta
) {
3223 const int legacyWidthSnappingMagicNumber
= 320;
3224 if (adjustedDescription
.maxWidth
.isFixed() && adjustedDescription
.maxWidth
.value() <= legacyWidthSnappingMagicNumber
)
3225 adjustedDescription
.maxWidth
= Length(DeviceWidth
);
3226 if (adjustedDescription
.maxHeight
.isFixed() && adjustedDescription
.maxHeight
.value() <= m_size
.height
)
3227 adjustedDescription
.maxHeight
= Length(DeviceHeight
);
3228 adjustedDescription
.minWidth
= adjustedDescription
.maxWidth
;
3229 adjustedDescription
.minHeight
= adjustedDescription
.maxHeight
;
3232 float oldInitialScale
= pageScaleConstraintsSet().pageDefinedConstraints().initialScale
;
3233 pageScaleConstraintsSet().updatePageDefinedConstraints(adjustedDescription
, defaultMinWidth
);
3235 if (settingsImpl()->clobberUserAgentInitialScaleQuirk()
3236 && pageScaleConstraintsSet().userAgentConstraints().initialScale
!= -1
3237 && pageScaleConstraintsSet().userAgentConstraints().initialScale
* deviceScaleFactor() <= 1) {
3238 if (description
.maxWidth
== Length(DeviceWidth
)
3239 || (description
.maxWidth
.type() == Auto
&& pageScaleConstraintsSet().pageDefinedConstraints().initialScale
== 1.0f
))
3240 setInitialPageScaleOverride(-1);
3243 pageScaleConstraintsSet().adjustForAndroidWebViewQuirks(adjustedDescription
, defaultMinWidth
.intValue(), deviceScaleFactor(), settingsImpl()->supportDeprecatedTargetDensityDPI(), page()->settings().wideViewportQuirkEnabled(), page()->settings().useWideViewport(), page()->settings().loadWithOverviewMode(), settingsImpl()->viewportMetaNonUserScalableQuirk());
3244 float newInitialScale
= pageScaleConstraintsSet().pageDefinedConstraints().initialScale
;
3245 if (oldInitialScale
!= newInitialScale
&& newInitialScale
!= -1) {
3246 pageScaleConstraintsSet().setNeedsReset(true);
3247 if (mainFrameImpl() && mainFrameImpl()->frameView())
3248 mainFrameImpl()->frameView()->setNeedsLayout();
3251 updateMainFrameLayoutSize();
3253 if (LocalFrame
* frame
= page()->deprecatedLocalMainFrame()) {
3254 if (TextAutosizer
* textAutosizer
= frame
->document()->textAutosizer())
3255 textAutosizer
->updatePageInfoInAllFrames();
3259 void WebViewImpl::updateMainFrameLayoutSize()
3261 if (m_shouldAutoResize
|| !mainFrameImpl())
3264 RefPtrWillBeRawPtr
<FrameView
> view
= mainFrameImpl()->frameView();
3268 WebSize layoutSize
= m_size
;
3270 if (settings()->viewportEnabled())
3271 layoutSize
= pageScaleConstraintsSet().layoutSize();
3273 if (page()->settings().forceZeroLayoutHeight())
3274 layoutSize
.height
= 0;
3276 view
->setLayoutSize(layoutSize
);
3278 // Resizing marks the frame as needsLayout. Inform clients so that they
3279 // will perform the layout. Widgets held by WebPluginContainerImpl do not otherwise
3280 // see this resize layout invalidation.
3282 client()->didUpdateLayoutSize(layoutSize
);
3285 IntSize
WebViewImpl::contentsSize() const
3287 if (!page()->mainFrame()->isLocalFrame())
3289 LayoutView
* root
= page()->deprecatedLocalMainFrame()->contentLayoutObject();
3292 return root
->documentRect().size();
3295 WebSize
WebViewImpl::contentsPreferredMinimumSize()
3299 Document
* document
= m_page
->mainFrame()->isLocalFrame() ? m_page
->deprecatedLocalMainFrame()->document() : 0;
3300 if (!document
|| !document
->layoutView() || !document
->documentElement() || !document
->documentElement()->layoutBox())
3303 int widthScaled
= document
->layoutView()->minPreferredLogicalWidth().round(); // Already accounts for zoom.
3304 int heightScaled
= document
->documentElement()->layoutBox()->scrollHeight().round();
3305 return IntSize(widthScaled
, heightScaled
);
3308 void WebViewImpl::setCompositedDisplayList(PassOwnPtr
<CompositedDisplayList
> compositedDisplayList
)
3310 m_compositedDisplayList
.assign(compositedDisplayList
);
3313 WebCompositedDisplayList
* WebViewImpl::compositedDisplayList()
3315 return &m_compositedDisplayList
;
3318 void WebViewImpl::enableViewport()
3320 settings()->setViewportEnabled(true);
3323 void WebViewImpl::disableViewport()
3325 settings()->setViewportEnabled(false);
3326 pageScaleConstraintsSet().clearPageDefinedConstraints();
3327 updateMainFrameLayoutSize();
3330 float WebViewImpl::defaultMinimumPageScaleFactor() const
3332 return pageScaleConstraintsSet().defaultConstraints().minimumScale
;
3335 float WebViewImpl::defaultMaximumPageScaleFactor() const
3337 return pageScaleConstraintsSet().defaultConstraints().maximumScale
;
3340 float WebViewImpl::minimumPageScaleFactor() const
3342 return pageScaleConstraintsSet().finalConstraints().minimumScale
;
3345 float WebViewImpl::maximumPageScaleFactor() const
3347 return pageScaleConstraintsSet().finalConstraints().maximumScale
;
3350 void WebViewImpl::resetScrollAndScaleState()
3352 resetScrollAndScaleState(false);
3355 void WebViewImpl::resetScrollAndScaleStateImmediately()
3357 resetScrollAndScaleState(true);
3360 void WebViewImpl::resetScrollAndScaleState(bool immediately
)
3362 page()->frameHost().visualViewport().reset();
3364 if (!page()->mainFrame()->isLocalFrame())
3367 if (FrameView
* frameView
= toLocalFrame(page()->mainFrame())->view()) {
3368 ScrollableArea
* scrollableArea
= frameView
->layoutViewportScrollableArea();
3370 if (scrollableArea
->scrollPositionDouble() != DoublePoint::zero())
3371 scrollableArea
->setScrollPosition(DoublePoint::zero(), ProgrammaticScroll
);
3374 pageScaleConstraintsSet().setNeedsReset(true);
3376 refreshPageScaleFactorAfterLayout();
3378 // Clobber saved scales and scroll offsets.
3379 if (FrameView
* view
= page()->deprecatedLocalMainFrame()->document()->view())
3380 view
->cacheCurrentScrollPosition();
3383 void WebViewImpl::performMediaPlayerAction(const WebMediaPlayerAction
& action
,
3384 const WebPoint
& location
)
3386 HitTestResult result
= hitTestResultForViewportPos(location
);
3387 RefPtrWillBeRawPtr
<Node
> node
= result
.innerNode();
3388 if (!isHTMLVideoElement(*node
) && !isHTMLAudioElement(*node
))
3391 RefPtrWillBeRawPtr
<HTMLMediaElement
> mediaElement
= static_pointer_cast
<HTMLMediaElement
>(node
);
3392 switch (action
.type
) {
3393 case WebMediaPlayerAction::Play
:
3395 mediaElement
->play();
3397 mediaElement
->pause();
3399 case WebMediaPlayerAction::Mute
:
3400 mediaElement
->setMuted(action
.enable
);
3402 case WebMediaPlayerAction::Loop
:
3403 mediaElement
->setLoop(action
.enable
);
3405 case WebMediaPlayerAction::Controls
:
3406 mediaElement
->setBooleanAttribute(HTMLNames::controlsAttr
, action
.enable
);
3409 ASSERT_NOT_REACHED();
3413 void WebViewImpl::performPluginAction(const WebPluginAction
& action
,
3414 const WebPoint
& location
)
3416 // FIXME: Location is probably in viewport coordinates
3417 HitTestResult result
= hitTestResultForRootFramePos(location
);
3418 RefPtrWillBeRawPtr
<Node
> node
= result
.innerNode();
3419 if (!isHTMLObjectElement(*node
) && !isHTMLEmbedElement(*node
))
3422 LayoutObject
* object
= node
->layoutObject();
3423 if (object
&& object
->isLayoutPart()) {
3424 Widget
* widget
= toLayoutPart(object
)->widget();
3425 if (widget
&& widget
->isPluginContainer()) {
3426 WebPluginContainerImpl
* plugin
= toWebPluginContainerImpl(widget
);
3427 switch (action
.type
) {
3428 case WebPluginAction::Rotate90Clockwise
:
3429 plugin
->plugin()->rotateView(WebPlugin::RotationType90Clockwise
);
3431 case WebPluginAction::Rotate90Counterclockwise
:
3432 plugin
->plugin()->rotateView(WebPlugin::RotationType90Counterclockwise
);
3435 ASSERT_NOT_REACHED();
3441 WebHitTestResult
WebViewImpl::hitTestResultAt(const WebPoint
& point
)
3443 return coreHitTestResultAt(point
);
3446 HitTestResult
WebViewImpl::coreHitTestResultAt(const WebPoint
& pointInViewport
)
3448 FrameView
* view
= mainFrameImpl()->frameView();
3449 IntPoint pointInRootFrame
= view
->contentsToFrame(view
->viewportToContents(pointInViewport
));
3450 return hitTestResultForRootFramePos(pointInRootFrame
);
3453 void WebViewImpl::copyImageAt(const WebPoint
& point
)
3458 HitTestResult result
= hitTestResultForViewportPos(point
);
3459 if (!isHTMLCanvasElement(result
.innerNodeOrImageMapImage()) && result
.absoluteImageURL().isEmpty()) {
3460 // There isn't actually an image at these coordinates. Might be because
3461 // the window scrolled while the context menu was open or because the page
3462 // changed itself between when we thought there was an image here and when
3463 // we actually tried to retreive the image.
3465 // FIXME: implement a cache of the most recent HitTestResult to avoid having
3466 // to do two hit tests.
3470 m_page
->deprecatedLocalMainFrame()->editor().copyImage(result
);
3473 void WebViewImpl::saveImageAt(const WebPoint
& point
)
3478 Node
* node
= hitTestResultForViewportPos(point
).innerNodeOrImageMapImage();
3479 if (!node
|| !(isHTMLCanvasElement(*node
) || isHTMLImageElement(*node
)))
3482 String url
= toElement(*node
).imageSourceURL();
3483 if (!KURL(KURL(), url
).protocolIsData())
3486 m_client
->saveImageFromDataURL(url
);
3489 void WebViewImpl::dragSourceEndedAt(
3490 const WebPoint
& clientPoint
,
3491 const WebPoint
& screenPoint
,
3492 WebDragOperation operation
)
3494 PlatformMouseEvent
pme(clientPoint
, screenPoint
, LeftButton
, PlatformEvent::MouseMoved
,
3495 0, false, false, false, false, PlatformMouseEvent::RealOrIndistinguishable
, 0);
3496 m_page
->deprecatedLocalMainFrame()->eventHandler().dragSourceEndedAt(pme
,
3497 static_cast<DragOperation
>(operation
));
3500 void WebViewImpl::dragSourceSystemDragEnded()
3502 // It's possible for us to get this callback while not doing a drag if
3503 // it's from a previous page that got unloaded.
3504 if (m_doingDragAndDrop
) {
3505 m_page
->dragController().dragEnded();
3506 m_doingDragAndDrop
= false;
3510 WebDragOperation
WebViewImpl::dragTargetDragEnter(
3511 const WebDragData
& webDragData
,
3512 const WebPoint
& clientPoint
,
3513 const WebPoint
& screenPoint
,
3514 WebDragOperationsMask operationsAllowed
,
3517 ASSERT(!m_currentDragData
);
3519 m_currentDragData
= DataObject::create(webDragData
);
3520 m_operationsAllowed
= operationsAllowed
;
3522 return dragTargetDragEnterOrOver(clientPoint
, screenPoint
, DragEnter
, modifiers
);
3525 WebDragOperation
WebViewImpl::dragTargetDragOver(
3526 const WebPoint
& clientPoint
,
3527 const WebPoint
& screenPoint
,
3528 WebDragOperationsMask operationsAllowed
,
3531 m_operationsAllowed
= operationsAllowed
;
3533 return dragTargetDragEnterOrOver(clientPoint
, screenPoint
, DragOver
, modifiers
);
3536 void WebViewImpl::dragTargetDragLeave()
3538 ASSERT(m_currentDragData
);
3541 m_currentDragData
.get(),
3544 static_cast<DragOperation
>(m_operationsAllowed
));
3546 m_page
->dragController().dragExited(&dragData
);
3548 // FIXME: why is the drag scroll timer not stopped here?
3550 m_dragOperation
= WebDragOperationNone
;
3551 m_currentDragData
= nullptr;
3554 void WebViewImpl::dragTargetDrop(const WebPoint
& clientPoint
,
3555 const WebPoint
& screenPoint
,
3558 ASSERT(m_currentDragData
);
3560 WebAutofillClient
* autofillClient
= mainFrameImpl() ? mainFrameImpl()->autofillClient() : 0;
3561 UserGestureNotifier
notifier(autofillClient
, &m_userGestureObserved
);
3563 // If this webview transitions from the "drop accepting" state to the "not
3564 // accepting" state, then our IPC message reply indicating that may be in-
3565 // flight, or else delayed by javascript processing in this webview. If a
3566 // drop happens before our IPC reply has reached the browser process, then
3567 // the browser forwards the drop to this webview. So only allow a drop to
3568 // proceed if our webview m_dragOperation state is not DragOperationNone.
3570 if (m_dragOperation
== WebDragOperationNone
) { // IPC RACE CONDITION: do not allow this drop.
3571 dragTargetDragLeave();
3575 m_currentDragData
->setModifiers(toPlatformMouseEventModifiers(modifiers
));
3577 m_currentDragData
.get(),
3580 static_cast<DragOperation
>(m_operationsAllowed
));
3582 UserGestureIndicator
gesture(DefinitelyProcessingNewUserGesture
);
3583 m_page
->dragController().performDrag(&dragData
);
3585 m_dragOperation
= WebDragOperationNone
;
3586 m_currentDragData
= nullptr;
3589 void WebViewImpl::spellingMarkers(WebVector
<uint32_t>* markers
)
3591 Vector
<uint32_t> result
;
3592 for (Frame
* frame
= m_page
->mainFrame(); frame
; frame
= frame
->tree().traverseNext()) {
3593 if (!frame
->isLocalFrame())
3595 const DocumentMarkerVector
& documentMarkers
= toLocalFrame(frame
)->document()->markers().markers();
3596 for (size_t i
= 0; i
< documentMarkers
.size(); ++i
)
3597 result
.append(documentMarkers
[i
]->hash());
3599 markers
->assign(result
);
3602 void WebViewImpl::removeSpellingMarkersUnderWords(const WebVector
<WebString
>& words
)
3604 Vector
<String
> convertedWords
;
3605 convertedWords
.append(words
.data(), words
.size());
3607 for (Frame
* frame
= m_page
->mainFrame(); frame
; frame
= frame
->tree().traverseNext()) {
3608 if (frame
->isLocalFrame())
3609 toLocalFrame(frame
)->removeSpellingMarkersUnderWords(convertedWords
);
3613 WebDragOperation
WebViewImpl::dragTargetDragEnterOrOver(const WebPoint
& clientPoint
, const WebPoint
& screenPoint
, DragAction dragAction
, int modifiers
)
3615 ASSERT(m_currentDragData
);
3617 m_currentDragData
->setModifiers(toPlatformMouseEventModifiers(modifiers
));
3619 m_currentDragData
.get(),
3622 static_cast<DragOperation
>(m_operationsAllowed
));
3624 DragSession dragSession
;
3625 if (dragAction
== DragEnter
)
3626 dragSession
= m_page
->dragController().dragEntered(&dragData
);
3628 dragSession
= m_page
->dragController().dragUpdated(&dragData
);
3630 DragOperation dropEffect
= dragSession
.operation
;
3632 // Mask the drop effect operation against the drag source's allowed operations.
3633 if (!(dropEffect
& dragData
.draggingSourceOperationMask()))
3634 dropEffect
= DragOperationNone
;
3636 m_dragOperation
= static_cast<WebDragOperation
>(dropEffect
);
3638 return m_dragOperation
;
3641 void WebViewImpl::sendResizeEventAndRepaint()
3643 // FIXME: This is wrong. The FrameView is responsible sending a resizeEvent
3644 // as part of layout. Layout is also responsible for sending invalidations
3645 // to the embedder. This method and all callers may be wrong. -- eseidel.
3646 if (mainFrameImpl()->frameView()) {
3647 // Enqueues the resize event.
3648 mainFrameImpl()->frame()->document()->enqueueResizeEvent();
3652 if (m_layerTreeView
) {
3653 updateLayerTreeViewport();
3655 WebRect
damagedRect(0, 0, m_size
.width
, m_size
.height
);
3656 m_client
->didInvalidateRect(damagedRect
);
3659 updatePageOverlays();
3660 m_devToolsEmulator
->viewportChanged();
3663 void WebViewImpl::configureAutoResizeMode()
3665 if (!mainFrameImpl() || !mainFrameImpl()->frame() || !mainFrameImpl()->frame()->view())
3668 if (m_shouldAutoResize
)
3669 mainFrameImpl()->frame()->view()->enableAutoSizeMode(m_minAutoSize
, m_maxAutoSize
);
3671 mainFrameImpl()->frame()->view()->disableAutoSizeMode();
3674 unsigned long WebViewImpl::createUniqueIdentifierForRequest()
3676 return createUniqueIdentifier();
3679 void WebViewImpl::setCompositorDeviceScaleFactorOverride(float deviceScaleFactor
)
3681 if (m_compositorDeviceScaleFactorOverride
== deviceScaleFactor
)
3683 m_compositorDeviceScaleFactorOverride
= deviceScaleFactor
;
3684 if (page() && m_layerTreeView
)
3685 updateLayerTreeDeviceScaleFactor();
3688 void WebViewImpl::setRootLayerTransform(const WebSize
& rootLayerOffset
, float rootLayerScale
)
3690 if (m_rootLayerScale
== rootLayerScale
&& m_rootLayerOffset
== rootLayerOffset
)
3692 m_rootLayerScale
= rootLayerScale
;
3693 m_rootLayerOffset
= rootLayerOffset
;
3694 if (mainFrameImpl())
3695 mainFrameImpl()->setInputEventsTransformForEmulation(m_rootLayerOffset
, m_rootLayerScale
);
3696 updateRootLayerTransform();
3699 void WebViewImpl::enableDeviceEmulation(const WebDeviceEmulationParams
& params
)
3701 m_devToolsEmulator
->enableDeviceEmulation(params
);
3704 void WebViewImpl::disableDeviceEmulation()
3706 m_devToolsEmulator
->disableDeviceEmulation();
3709 WebAXObject
WebViewImpl::accessibilityObject()
3711 if (!mainFrameImpl())
3712 return WebAXObject();
3714 Document
* document
= mainFrameImpl()->frame()->document();
3715 return WebAXObject(toAXObjectCacheImpl(document
->axObjectCache())->root());
3718 void WebViewImpl::performCustomContextMenuAction(unsigned action
)
3722 ContextMenu
* menu
= m_page
->contextMenuController().contextMenu();
3725 const ContextMenuItem
* item
= menu
->itemWithAction(static_cast<ContextMenuAction
>(ContextMenuItemBaseCustomTag
+ action
));
3727 m_page
->contextMenuController().contextMenuItemSelected(item
);
3728 m_page
->contextMenuController().clearContextMenu();
3731 void WebViewImpl::showContextMenu()
3736 page()->contextMenuController().clearContextMenu();
3738 ContextMenuAllowedScope scope
;
3739 if (LocalFrame
* focusedFrame
= toLocalFrame(page()->focusController().focusedOrMainFrame()))
3740 focusedFrame
->eventHandler().sendContextMenuEventForKey(nullptr);
3744 void WebViewImpl::extractSmartClipData(WebRect rectInViewport
, WebString
& clipText
, WebString
& clipHtml
, WebRect
& clipRectInViewport
)
3746 LocalFrame
* localFrame
= toLocalFrame(focusedCoreFrame());
3749 SmartClipData clipData
= SmartClip(localFrame
).dataForRect(rectInViewport
);
3750 clipText
= clipData
.clipData();
3751 clipRectInViewport
= clipData
.rectInViewport();
3753 WebLocalFrameImpl
* frame
= mainFrameImpl();
3756 WebPoint
startPoint(rectInViewport
.x
, rectInViewport
.y
);
3757 WebPoint
endPoint(rectInViewport
.x
+ rectInViewport
.width
, rectInViewport
.y
+ rectInViewport
.height
);
3758 VisiblePosition startVisiblePosition
= frame
->visiblePositionForViewportPoint(startPoint
);
3759 VisiblePosition endVisiblePosition
= frame
->visiblePositionForViewportPoint(endPoint
);
3761 Position startPosition
= startVisiblePosition
.deepEquivalent();
3762 Position endPosition
= endVisiblePosition
.deepEquivalent();
3764 // document() will return null if -webkit-user-select is set to none.
3765 if (!startPosition
.document() || !endPosition
.document())
3768 clipHtml
= createMarkup(startPosition
, endPosition
, AnnotateForInterchange
, ConvertBlocksToInlines::NotConvert
, ResolveNonLocalURLs
);
3771 void WebViewImpl::hidePopups()
3776 void WebViewImpl::setIsTransparent(bool isTransparent
)
3778 // Set any existing frames to be transparent.
3779 Frame
* frame
= m_page
->mainFrame();
3781 if (frame
->isLocalFrame())
3782 toLocalFrame(frame
)->view()->setTransparent(isTransparent
);
3783 frame
= frame
->tree().traverseNext();
3786 // Future frames check this to know whether to be transparent.
3787 m_isTransparent
= isTransparent
;
3789 if (m_layerTreeView
)
3790 m_layerTreeView
->setHasTransparentBackground(this->isTransparent());
3793 bool WebViewImpl::isTransparent() const
3795 return m_isTransparent
;
3798 void WebViewImpl::setBaseBackgroundColor(WebColor color
)
3802 if (m_baseBackgroundColor
== color
)
3805 m_baseBackgroundColor
= color
;
3807 if (m_page
->mainFrame() && m_page
->mainFrame()->isLocalFrame())
3808 m_page
->deprecatedLocalMainFrame()->view()->setBaseBackgroundColor(color
);
3810 updateLayerTreeBackgroundColor();
3813 void WebViewImpl::setIsActive(bool active
)
3816 page()->focusController().setActive(active
);
3819 bool WebViewImpl::isActive() const
3821 return page() ? page()->focusController().isActive() : false;
3824 void WebViewImpl::setDomainRelaxationForbidden(bool forbidden
, const WebString
& scheme
)
3826 SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(forbidden
, String(scheme
));
3829 void WebViewImpl::setWindowFeatures(const WebWindowFeatures
& features
)
3831 m_page
->chromeClient().setWindowFeatures(features
);
3834 void WebViewImpl::setOpenedByDOM()
3836 m_page
->setOpenedByDOM();
3839 void WebViewImpl::setSelectionColors(unsigned activeBackgroundColor
,
3840 unsigned activeForegroundColor
,
3841 unsigned inactiveBackgroundColor
,
3842 unsigned inactiveForegroundColor
) {
3843 #if USE(DEFAULT_RENDER_THEME)
3844 LayoutThemeDefault::setSelectionColors(activeBackgroundColor
, activeForegroundColor
, inactiveBackgroundColor
, inactiveForegroundColor
);
3845 LayoutTheme::theme().platformColorsDidChange();
3849 void WebViewImpl::didCommitLoad(bool isNewNavigation
, bool isNavigationWithinPage
)
3851 if (isNewNavigation
&& !isNavigationWithinPage
) {
3852 pageScaleConstraintsSet().setNeedsReset(true);
3853 m_pageImportanceSignals
.onCommitLoad();
3856 // Give the visual viewport's scroll layer its initial size.
3857 page()->frameHost().visualViewport().mainFrameDidChangeSize();
3859 // Make sure link highlight from previous page is cleared.
3860 m_linkHighlights
.clear();
3861 endActiveFlingAnimation();
3862 m_userGestureObserved
= false;
3865 void WebViewImpl::documentElementAvailable(WebLocalFrameImpl
* webframe
)
3867 if (webframe
!= mainFrameImpl())
3870 // For non-HTML documents the willInsertBody notification won't happen
3871 // so we resume as soon as we have a document element. Even for XHTML
3872 // documents there may never be a <body> (since the parser won't always
3873 // insert one), so we resume here too. That does mean XHTML documents make
3874 // frames when there's only a <head>, but such documents are pretty rare.
3875 if (!mainFrameImpl()->frame()->document()->isHTMLDocument())
3876 resumeTreeViewCommitsIfRenderingReady();
3879 void WebViewImpl::willInsertBody(WebLocalFrameImpl
* webframe
)
3881 if (webframe
!= mainFrameImpl())
3884 // If we get to the <body> try to resume commits since we should have content
3886 // TODO(esprehn): Is this really optimal? We might start producing frames
3887 // for very little content, should we wait for some herustic like
3888 // isVisuallyNonEmpty() ?
3889 resumeTreeViewCommitsIfRenderingReady();
3892 void WebViewImpl::didFinishDocumentLoad(WebLocalFrameImpl
* webframe
)
3894 if (webframe
!= mainFrameImpl())
3896 resumeTreeViewCommitsIfRenderingReady();
3899 void WebViewImpl::didRemoveAllPendingStylesheet(WebLocalFrameImpl
* webframe
)
3901 if (webframe
!= mainFrameImpl())
3904 Document
& document
= *mainFrameImpl()->frame()->document();
3906 // For HTML if we have no more stylesheets to load and we're past the body
3907 // tag, we should have something to paint so resume.
3908 if (document
.isHTMLDocument() && !document
.body())
3911 // For non-HTML there is no body so resume as soon as the sheets are loaded.
3912 if (!document
.isHTMLDocument() && !document
.documentElement())
3915 resumeTreeViewCommitsIfRenderingReady();
3918 void WebViewImpl::resumeTreeViewCommitsIfRenderingReady()
3920 LocalFrame
* frame
= mainFrameImpl()->frame();
3921 if (!frame
->loader().stateMachine()->committedFirstRealDocumentLoad())
3923 if (!frame
->document()->isRenderingReady())
3925 if (m_layerTreeView
) {
3926 m_layerTreeView
->setDeferCommits(false);
3927 m_layerTreeView
->setNeedsBeginFrame();
3931 void WebViewImpl::postLayoutResize(WebLocalFrameImpl
* webframe
)
3933 FrameView
* view
= webframe
->frame()->view();
3934 if (webframe
== mainFrame())
3935 view
->resize(mainFrameSize());
3937 view
->resize(webframe
->frameView()->size());
3940 void WebViewImpl::layoutUpdated(WebLocalFrameImpl
* webframe
)
3942 if (!m_client
|| !webframe
->frame()->isLocalRoot())
3945 if (m_shouldAutoResize
&& webframe
->frame() && webframe
->frame()->view()) {
3946 WebSize frameSize
= webframe
->frame()->view()->frameRect().size();
3947 if (frameSize
!= m_size
) {
3950 page()->frameHost().visualViewport().setSize(m_size
);
3951 pageScaleConstraintsSet().didChangeViewSize(m_size
);
3953 m_client
->didAutoResize(m_size
);
3954 sendResizeEventAndRepaint();
3958 if (pageScaleConstraintsSet().constraintsDirty())
3959 refreshPageScaleFactorAfterLayout();
3961 FrameView
* view
= webframe
->frame()->view();
3963 postLayoutResize(webframe
);
3965 // Relayout immediately to avoid violating the rule that needsLayout()
3966 // isn't set at the end of a layout.
3967 if (view
->needsLayout())
3970 // In case we didn't have a size when the top controls were updated.
3971 didUpdateTopControls();
3973 m_client
->didUpdateLayout();
3976 void WebViewImpl::didChangeContentsSize()
3978 pageScaleConstraintsSet().didChangeContentsSize(contentsSize(), pageScaleFactor());
3981 void WebViewImpl::pageScaleFactorChanged()
3983 pageScaleConstraintsSet().setNeedsReset(false);
3984 updateLayerTreeViewport();
3985 m_devToolsEmulator
->viewportChanged();
3986 m_client
->pageScaleFactorChanged();
3989 bool WebViewImpl::useExternalPopupMenus()
3991 return shouldUseExternalPopupMenus
;
3994 void WebViewImpl::startDragging(LocalFrame
* frame
,
3995 const WebDragData
& dragData
,
3996 WebDragOperationsMask mask
,
3997 const WebImage
& dragImage
,
3998 const WebPoint
& dragImageOffset
)
4002 ASSERT(!m_doingDragAndDrop
);
4003 m_doingDragAndDrop
= true;
4004 m_client
->startDragging(WebLocalFrameImpl::fromFrame(frame
), dragData
, mask
, dragImage
, dragImageOffset
);
4007 void WebViewImpl::setIgnoreInputEvents(bool newValue
)
4009 ASSERT(m_ignoreInputEvents
!= newValue
);
4010 m_ignoreInputEvents
= newValue
;
4013 void WebViewImpl::setBackgroundColorOverride(WebColor color
)
4015 m_backgroundColorOverride
= color
;
4016 updateLayerTreeBackgroundColor();
4019 void WebViewImpl::setZoomFactorOverride(float zoomFactor
)
4021 m_zoomFactorOverride
= zoomFactor
;
4022 setZoomLevel(zoomLevel());
4025 void WebViewImpl::setPageOverlayColor(WebColor color
)
4027 if (m_pageColorOverlay
)
4028 m_pageColorOverlay
.clear();
4030 if (color
== Color::transparent
)
4033 m_pageColorOverlay
= PageOverlay::create(this, new ColorOverlay(color
));
4034 m_pageColorOverlay
->update();
4037 WebPageImportanceSignals
* WebViewImpl::pageImportanceSignals()
4039 return &m_pageImportanceSignals
;
4042 Element
* WebViewImpl::focusedElement() const
4044 Frame
* frame
= m_page
->focusController().focusedFrame();
4045 if (!frame
|| !frame
->isLocalFrame())
4048 Document
* document
= toLocalFrame(frame
)->document();
4052 return document
->focusedElement();
4055 HitTestResult
WebViewImpl::hitTestResultForViewportPos(const IntPoint
& posInViewport
)
4057 IntPoint
rootFramePoint(m_page
->frameHost().visualViewport().viewportToRootFrame(posInViewport
));
4058 return hitTestResultForRootFramePos(rootFramePoint
);
4061 HitTestResult
WebViewImpl::hitTestResultForRootFramePos(const IntPoint
& posInRootFrame
)
4063 if (!m_page
->mainFrame()->isLocalFrame())
4064 return HitTestResult();
4065 IntPoint
docPoint(m_page
->deprecatedLocalMainFrame()->view()->rootFrameToContents(posInRootFrame
));
4066 HitTestResult result
= m_page
->deprecatedLocalMainFrame()->eventHandler().hitTestResultAtPoint(docPoint
, HitTestRequest::ReadOnly
| HitTestRequest::Active
);
4067 result
.setToShadowHostIfInUserAgentShadowRoot();
4071 WebHitTestResult
WebViewImpl::hitTestResultForTap(const WebPoint
& tapPointWindowPos
, const WebSize
& tapArea
)
4073 if (!m_page
->mainFrame()->isLocalFrame())
4074 return HitTestResult();
4076 WebGestureEvent tapEvent
;
4077 tapEvent
.x
= tapPointWindowPos
.x
;
4078 tapEvent
.y
= tapPointWindowPos
.y
;
4079 tapEvent
.type
= WebInputEvent::GestureTap
;
4080 tapEvent
.data
.tap
.tapCount
= 1;
4081 tapEvent
.data
.tap
.width
= tapArea
.width
;
4082 tapEvent
.data
.tap
.height
= tapArea
.height
;
4084 PlatformGestureEventBuilder
platformEvent(mainFrameImpl()->frameView(), tapEvent
);
4086 HitTestResult result
= m_page
->deprecatedLocalMainFrame()->eventHandler().hitTestResultForGestureEvent(platformEvent
, HitTestRequest::ReadOnly
| HitTestRequest::Active
).hitTestResult();
4088 result
.setToShadowHostIfInUserAgentShadowRoot();
4092 void WebViewImpl::setTabsToLinks(bool enable
)
4094 m_tabsToLinks
= enable
;
4097 bool WebViewImpl::tabsToLinks() const
4099 return m_tabsToLinks
;
4102 void WebViewImpl::setRootGraphicsLayer(GraphicsLayer
* layer
)
4104 if (!m_layerTreeView
)
4107 VisualViewport
& visualViewport
= page()->frameHost().visualViewport();
4108 visualViewport
.attachToLayerTree(layer
, graphicsLayerFactory());
4110 m_rootGraphicsLayer
= visualViewport
.rootGraphicsLayer();
4111 m_rootLayer
= visualViewport
.rootGraphicsLayer()->platformLayer();
4112 m_rootTransformLayer
= visualViewport
.rootGraphicsLayer();
4113 updateRootLayerTransform();
4114 m_layerTreeView
->setRootLayer(*m_rootLayer
);
4115 // We register viewport layers here since there may not be a layer
4116 // tree view prior to this point.
4117 page()->frameHost().visualViewport().registerLayersWithTreeView(m_layerTreeView
);
4118 updatePageOverlays();
4119 // TODO(enne): Work around page visibility changes not being
4120 // propogated to the WebView in some circumstances. This needs to
4121 // be refreshed here when setting a new root layer to avoid being
4122 // stuck in a presumed incorrectly invisible state.
4123 bool visible
= page()->visibilityState() == PageVisibilityStateVisible
;
4124 m_layerTreeView
->setVisible(visible
);
4126 m_rootGraphicsLayer
= nullptr;
4127 m_rootLayer
= nullptr;
4128 m_rootTransformLayer
= nullptr;
4129 // This means that we're transitioning to a new page. Suppress
4130 // commits until Blink generates invalidations so we don't
4131 // attempt to paint too early in the next page load.
4132 m_layerTreeView
->setDeferCommits(true);
4133 m_layerTreeView
->clearRootLayer();
4134 m_shouldDispatchFirstVisuallyNonEmptyLayout
= true;
4135 m_shouldDispatchFirstLayoutAfterFinishedParsing
= true;
4136 page()->frameHost().visualViewport().clearLayersForTreeView(m_layerTreeView
);
4140 void WebViewImpl::invalidateRect(const IntRect
& rect
)
4142 if (m_layerTreeView
)
4143 updateLayerTreeViewport();
4145 m_client
->didInvalidateRect(rect
);
4148 GraphicsLayerFactory
* WebViewImpl::graphicsLayerFactory() const
4150 return m_graphicsLayerFactory
.get();
4153 DeprecatedPaintLayerCompositor
* WebViewImpl::compositor() const
4155 if (!page() || !page()->mainFrame() || !page()->mainFrame()->isLocalFrame())
4158 if (!page()->deprecatedLocalMainFrame()->document() || !page()->deprecatedLocalMainFrame()->document()->layoutView())
4161 return page()->deprecatedLocalMainFrame()->document()->layoutView()->compositor();
4164 void WebViewImpl::registerForAnimations(WebLayer
* layer
)
4166 if (m_layerTreeView
)
4167 m_layerTreeView
->registerForAnimations(layer
);
4170 GraphicsLayer
* WebViewImpl::rootGraphicsLayer()
4172 return m_rootGraphicsLayer
;
4175 void WebViewImpl::scheduleAnimation()
4177 if (m_layerTreeView
) {
4178 m_layerTreeView
->setNeedsBeginFrame();
4182 m_client
->scheduleAnimation();
4185 void WebViewImpl::attachCompositorAnimationTimeline(WebCompositorAnimationTimeline
* timeline
)
4187 if (m_layerTreeView
)
4188 m_layerTreeView
->attachCompositorAnimationTimeline(timeline
);
4191 void WebViewImpl::detachCompositorAnimationTimeline(WebCompositorAnimationTimeline
* timeline
)
4193 if (m_layerTreeView
)
4194 m_layerTreeView
->detachCompositorAnimationTimeline(timeline
);
4197 void WebViewImpl::initializeLayerTreeView()
4200 m_client
->initializeLayerTreeView();
4201 m_layerTreeView
= m_client
->layerTreeView();
4204 if (WebDevToolsAgentImpl
* devTools
= mainFrameDevToolsAgentImpl())
4205 devTools
->layerTreeViewChanged(m_layerTreeView
);
4207 m_page
->settings().setAcceleratedCompositingEnabled(m_layerTreeView
!= 0);
4209 // FIXME: only unittests, click to play, Android priting, and printing (for headers and footers)
4210 // make this assert necessary. We should make them not hit this code and then delete allowsBrokenNullLayerTreeView.
4211 ASSERT(m_layerTreeView
|| !m_client
|| m_client
->allowsBrokenNullLayerTreeView());
4213 if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled() && Platform::current()->isThreadedAnimationEnabled() && m_layerTreeView
) {
4214 ASSERT(Platform::current()->compositorSupport());
4215 m_linkHighlightsTimeline
= adoptPtr(Platform::current()->compositorSupport()->createAnimationTimeline());
4216 attachCompositorAnimationTimeline(m_linkHighlightsTimeline
.get());
4220 void WebViewImpl::applyViewportDeltas(
4221 const WebFloatSize
& visualViewportDelta
,
4222 const WebFloatSize
& layoutViewportDelta
,
4223 const WebFloatSize
& elasticOverscrollDelta
,
4224 float pageScaleDelta
,
4225 float topControlsShownRatioDelta
)
4227 if (!mainFrameImpl())
4229 FrameView
* frameView
= mainFrameImpl()->frameView();
4233 topControls().setShownRatio(topControls().shownRatio() + topControlsShownRatioDelta
);
4235 FloatPoint visualViewportOffset
= page()->frameHost().visualViewport().visibleRect().location();
4236 visualViewportOffset
.move(visualViewportDelta
.width
, visualViewportDelta
.height
);
4237 setPageScaleFactorAndLocation(pageScaleFactor() * pageScaleDelta
, visualViewportOffset
);
4239 if (pageScaleDelta
!= 1)
4240 m_doubleTapZoomPending
= false;
4242 m_elasticOverscroll
+= elasticOverscrollDelta
;
4243 frameView
->didUpdateElasticOverscroll();
4245 ScrollableArea
* layoutViewport
= frameView
->layoutViewportScrollableArea();
4247 DoublePoint layoutViewportPosition
= layoutViewport
->scrollPositionDouble()
4248 + DoubleSize(layoutViewportDelta
.width
, layoutViewportDelta
.height
);
4250 if (layoutViewport
->scrollPositionDouble() != layoutViewportPosition
) {
4251 layoutViewport
->setScrollPosition(layoutViewportPosition
, CompositorScroll
);
4252 if (DocumentLoader
* documentLoader
= mainFrameImpl()->frame()->loader().documentLoader())
4253 documentLoader
->initialScrollState().wasScrolledByUser
= true;
4257 void WebViewImpl::recordFrameTimingEvent(FrameTimingEventType eventType
, int64_t FrameId
, const WebVector
<WebFrameTimingEvent
>& events
)
4259 Frame
* frame
= m_page
? m_page
->mainFrame() : 0;
4261 while (frame
&& frame
->frameID() != FrameId
) {
4262 frame
= frame
->tree().traverseNext();
4265 if (!frame
|| !frame
->domWindow() || !frame
->domWindow()->document())
4266 return; // Can't find frame, it may have been cleaned up from the DOM.
4268 blink::DOMWindow
* domWindow
= frame
->domWindow();
4269 blink::Performance
* performance
= DOMWindowPerformance::performance(*domWindow
);
4270 for (size_t i
= 0; i
< events
.size(); ++i
) {
4271 if (eventType
== CompositeEvent
)
4272 performance
->addCompositeTiming(domWindow
->document(), events
[i
].sourceFrame
, events
[i
].startTime
);
4273 else if (eventType
== RenderEvent
)
4274 performance
->addRenderTiming(domWindow
->document(), events
[i
].sourceFrame
, events
[i
].startTime
, events
[i
].finishTime
);
4278 void WebViewImpl::updateLayerTreeViewport()
4280 if (!page() || !m_layerTreeView
)
4283 m_layerTreeView
->setPageScaleFactorAndLimits(pageScaleFactor(), minimumPageScaleFactor(), maximumPageScaleFactor());
4286 void WebViewImpl::updateLayerTreeBackgroundColor()
4288 if (!m_layerTreeView
)
4291 m_layerTreeView
->setBackgroundColor(alphaChannel(m_backgroundColorOverride
) ? m_backgroundColorOverride
: backgroundColor());
4294 void WebViewImpl::updateLayerTreeDeviceScaleFactor()
4297 ASSERT(m_layerTreeView
);
4299 float deviceScaleFactor
= m_compositorDeviceScaleFactorOverride
? m_compositorDeviceScaleFactorOverride
: page()->deviceScaleFactor();
4300 m_layerTreeView
->setDeviceScaleFactor(deviceScaleFactor
);
4303 void WebViewImpl::updateRootLayerTransform()
4305 // If we don't have a root graphics layer, we won't bother trying to find
4306 // or update the transform layer.
4307 if (!m_rootGraphicsLayer
)
4310 if (m_rootTransformLayer
) {
4311 TransformationMatrix transform
;
4312 transform
.translate(m_rootLayerOffset
.width
, m_rootLayerOffset
.height
);
4313 transform
= transform
.scale(m_rootLayerScale
);
4314 m_rootTransformLayer
->setTransform(transform
);
4318 bool WebViewImpl::detectContentOnTouch(const GestureEventWithHitTestResults
& targetedEvent
)
4320 if (!m_page
->mainFrame()->isLocalFrame())
4323 // Need a local copy of the hit test as setToShadowHostIfInUserAgentShadowRoot() will modify it.
4324 HitTestResult touchHit
= targetedEvent
.hitTestResult();
4325 touchHit
.setToShadowHostIfInUserAgentShadowRoot();
4327 if (touchHit
.isContentEditable())
4330 Node
* node
= touchHit
.innerNode();
4331 if (!node
|| !node
->isTextNode())
4334 // Ignore when tapping on links or nodes listening to click events, unless the click event is on the
4335 // body element, in which case it's unlikely that the original node itself was intended to be clickable.
4336 for (; node
&& !isHTMLBodyElement(*node
); node
= LayoutTreeBuilderTraversal::parent(*node
)) {
4337 if (node
->isLink() || node
->willRespondToTouchEvents() || node
->willRespondToMouseClickEvents())
4341 WebContentDetectionResult content
= m_client
->detectContentAround(touchHit
);
4342 if (!content
.isValid())
4345 m_client
->scheduleContentIntent(content
.intent());
4349 void WebViewImpl::setVisibilityState(WebPageVisibilityState visibilityState
,
4350 bool isInitialState
) {
4351 ASSERT(visibilityState
== WebPageVisibilityStateVisible
|| visibilityState
== WebPageVisibilityStateHidden
|| visibilityState
== WebPageVisibilityStatePrerender
);
4354 m_page
->setVisibilityState(static_cast<PageVisibilityState
>(static_cast<int>(visibilityState
)), isInitialState
);
4356 if (m_layerTreeView
) {
4357 bool visible
= visibilityState
== WebPageVisibilityStateVisible
;
4358 m_layerTreeView
->setVisible(visible
);
4362 bool WebViewImpl::requestPointerLock()
4364 return m_client
&& m_client
->requestPointerLock();
4367 void WebViewImpl::requestPointerUnlock()
4370 m_client
->requestPointerUnlock();
4373 bool WebViewImpl::isPointerLocked()
4375 return m_client
&& m_client
->isPointerLocked();
4378 void WebViewImpl::pointerLockMouseEvent(const WebInputEvent
& event
)
4380 OwnPtr
<UserGestureIndicator
> gestureIndicator
;
4381 AtomicString eventType
;
4382 switch (event
.type
) {
4383 case WebInputEvent::MouseDown
:
4384 eventType
= EventTypeNames::mousedown
;
4385 gestureIndicator
= adoptPtr(new UserGestureIndicator(DefinitelyProcessingNewUserGesture
));
4386 m_pointerLockGestureToken
= gestureIndicator
->currentToken();
4388 case WebInputEvent::MouseUp
:
4389 eventType
= EventTypeNames::mouseup
;
4390 gestureIndicator
= adoptPtr(new UserGestureIndicator(m_pointerLockGestureToken
.release()));
4392 case WebInputEvent::MouseMove
:
4393 eventType
= EventTypeNames::mousemove
;
4396 ASSERT_NOT_REACHED();
4399 const WebMouseEvent
& mouseEvent
= static_cast<const WebMouseEvent
&>(event
);
4402 page()->pointerLockController().dispatchLockedMouseEvent(
4403 PlatformMouseEventBuilder(mainFrameImpl()->frameView(), mouseEvent
),
4407 bool WebViewImpl::shouldDisableDesktopWorkarounds()
4409 if (!settings()->viewportEnabled())
4412 // A document is considered adapted to small screen UAs if one of these holds:
4413 // 1. The author specified viewport has a constrained width that is equal to
4414 // the initial viewport width.
4415 // 2. The author has disabled viewport zoom.
4417 const PageScaleConstraints
& constraints
= pageScaleConstraintsSet().pageDefinedConstraints();
4419 if (!mainFrameImpl() || !mainFrameImpl()->frameView())
4422 return mainFrameImpl()->frameView()->layoutSize().width() == m_size
.width
4423 || (constraints
.minimumScale
== constraints
.maximumScale
&& constraints
.minimumScale
!= -1);
4426 void WebViewImpl::forceNextWebGLContextCreationToFail()
4428 WebGLRenderingContext::forceNextWebGLContextCreationToFail();
4431 void WebViewImpl::forceNextDrawingBufferCreationToFail()
4433 DrawingBuffer::forceNextDrawingBufferCreationToFail();
4436 void WebViewImpl::updatePageOverlays()
4438 if (m_pageColorOverlay
)
4439 m_pageColorOverlay
->update();
4440 if (InspectorOverlayImpl
* overlay
= inspectorOverlay()) {
4441 PageOverlay
* inspectorPageOverlay
= overlay
->pageOverlay();
4442 if (inspectorPageOverlay
)
4443 inspectorPageOverlay
->update();
4447 } // namespace blink