Index: third_party/WebKit/Source/web/DevToolsEmulator.cpp |
diff --git a/third_party/WebKit/Source/web/DevToolsEmulator.cpp b/third_party/WebKit/Source/web/DevToolsEmulator.cpp |
index 848f4e121489e3eb3daee48891475e134128abbc..cf66ec0cc6c3a85a96c04f581d642422d6d9037b 100644 |
--- a/third_party/WebKit/Source/web/DevToolsEmulator.cpp |
+++ b/third_party/WebKit/Source/web/DevToolsEmulator.cpp |
@@ -11,6 +11,7 @@ |
#include "core/page/Page.h" |
#include "core/style/ComputedStyle.h" |
#include "platform/RuntimeEnabledFeatures.h" |
+#include "platform/geometry/FloatRect.h" |
#include "public/platform/WebLayerTreeView.h" |
#include "web/WebInputEventConversion.h" |
#include "web/WebLocalFrameImpl.h" |
@@ -219,7 +220,7 @@ void DevToolsEmulator::enableDeviceEmulation(const WebDeviceEmulationParams& par |
disableMobileEmulation(); |
m_webViewImpl->setCompositorDeviceScaleFactorOverride(params.deviceScaleFactor); |
- m_webViewImpl->setRootLayerTransform(WebSize(params.offset.x, params.offset.y), params.scale); |
+ updateRootLayerTransform(); |
// TODO(dgozman): mainFrameImpl() is null when it's remote. Figure out how |
// we end up with enabling emulation in this case. |
if (m_webViewImpl->mainFrameImpl()) { |
@@ -238,8 +239,8 @@ void DevToolsEmulator::disableDeviceEmulation() |
m_webViewImpl->page()->settings().setDeviceScaleAdjustment(m_embedderDeviceScaleAdjustment); |
disableMobileEmulation(); |
m_webViewImpl->setCompositorDeviceScaleFactorOverride(0.f); |
- m_webViewImpl->setRootLayerTransform(WebSize(0.f, 0.f), 1.f); |
m_webViewImpl->setPageScaleFactor(1.f); |
+ updateRootLayerTransform(); |
// mainFrameImpl() could be null during cleanup or remote <-> local swap. |
if (m_webViewImpl->mainFrameImpl()) { |
if (Document* document = m_webViewImpl->mainFrameImpl()->frame()->document()) |
@@ -319,6 +320,105 @@ void DevToolsEmulator::disableMobileEmulation() |
m_webViewImpl->mainFrameImpl()->frameView()->layout(); |
} |
+void DevToolsEmulator::setCompositedAreaOverride(const WebFloatRect& area, float scale) |
+{ |
+ if (!m_compositedAreaOverride) |
+ m_compositedAreaOverride = CompositedAreaOverride(); |
+ |
+ m_compositedAreaOverride->area = area; |
+ m_compositedAreaOverride->scale = scale; |
+ |
+ // Ensure that all content inside the area is recorded. |
+ if (m_webViewImpl->mainFrameImpl()) |
+ m_webViewImpl->mainFrameImpl()->frameView()->setVisibleContentRectForRecording(enclosingIntRect(area)); |
+ |
+ // Disable clipping on the visual viewport layer, to ensure the whole area is painted. |
+ GraphicsLayer* containerLayer = m_webViewImpl->page()->frameHost().visualViewport().containerLayer(); |
+ if (containerLayer) { |
+ m_compositedAreaOverride->originalVisualViewportMasking = containerLayer->masksToBounds(); |
+ containerLayer->setMasksToBounds(false); |
+ } |
+ |
+ // Move the correct (scaled) content area to show in the top left of the |
+ // CompositorFrame via the root transform. |
+ updateRootLayerTransform(); |
+} |
+ |
+void DevToolsEmulator::clearCompositedAreaOverride() |
+{ |
+ if (!m_compositedAreaOverride) |
+ return; |
+ |
+ bool originalMasking = m_compositedAreaOverride->originalVisualViewportMasking; |
+ m_compositedAreaOverride = WTF::nullopt; |
+ |
+ // Restore original state. |
+ if (m_webViewImpl->mainFrameImpl()) |
+ m_webViewImpl->mainFrameImpl()->frameView()->resetVisibleContentRectForRecording(); |
+ GraphicsLayer* containerLayer = m_webViewImpl->page()->frameHost().visualViewport().containerLayer(); |
+ if (containerLayer) |
+ containerLayer->setMasksToBounds(originalMasking); |
+ updateRootLayerTransform(); |
+} |
+ |
+void DevToolsEmulator::mainFrameScrollOrScaleChanged() |
+{ |
+ // Composited area override has to take current page scale and scroll |
+ // offset into account. Update the transform if it is active. |
+ if (m_compositedAreaOverride) |
+ updateRootLayerTransform(); |
+} |
+ |
+void DevToolsEmulator::applyDeviceEmulationTransform(TransformationMatrix* transform) |
+{ |
+ if (m_deviceMetricsEnabled) { |
+ WebSize offset(m_emulationParams.offset.x, m_emulationParams.offset.y); |
+ // Scale first, so that translation is unaffected. |
+ transform->translate(offset.width, offset.height); |
+ transform->scale(m_emulationParams.scale); |
+ if (m_webViewImpl->mainFrameImpl()) |
+ m_webViewImpl->mainFrameImpl()->setInputEventsTransformForEmulation(offset, m_emulationParams.scale); |
+ } else { |
+ if (m_webViewImpl->mainFrameImpl()) |
+ m_webViewImpl->mainFrameImpl()->setInputEventsTransformForEmulation(WebSize(0, 0), 1.0); |
+ } |
+} |
+ |
+void DevToolsEmulator::applyCompositedAreaOverrideTransform(TransformationMatrix* transform) |
+{ |
+ if (!m_compositedAreaOverride) |
+ return; |
+ |
+ // Transform operations follow in reverse application. |
+ // Last, scale positioned area according to override. |
+ transform->scale(m_compositedAreaOverride->scale); |
+ |
+ // Translate while taking into account current scroll offset. |
+ WebSize scrollOffset = m_webViewImpl->mainFrame()->scrollOffset(); |
+ WebFloatPoint visualOffset = m_webViewImpl->visualViewportOffset(); |
+ float scrollX = scrollOffset.width + visualOffset.x; |
+ float scrollY = scrollOffset.height + visualOffset.y; |
+ transform->translate( |
+ -m_compositedAreaOverride->area.x + scrollX, |
+ -m_compositedAreaOverride->area.y + scrollY); |
+ |
+ // First, reverse page scale, so we don't have to take it into account for |
+ // calculation of the translation. |
+ transform->scale(1. / m_webViewImpl->pageScaleFactor()); |
+} |
+ |
+void DevToolsEmulator::updateRootLayerTransform() |
+{ |
+ TransformationMatrix transform; |
+ |
+ // Apply device emulation transform first, so that it is affected by the |
+ // composited area override transform. |
+ applyCompositedAreaOverrideTransform(&transform); |
+ applyDeviceEmulationTransform(&transform); |
+ |
+ m_webViewImpl->setRootLayerTransform(transform); |
+} |
+ |
void DevToolsEmulator::setTouchEventEmulationEnabled(bool enabled) |
{ |
if (m_touchEventEmulationEnabled == enabled) |