 Chromium Code Reviews
 Chromium Code Reviews Issue 2237433004:
  Adds DevTools commands for forced viewport override.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 2237433004:
  Adds DevTools commands for forced viewport override.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| 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..2807b12b1f32004f38f68a5b3e0df84abc2e3cec 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::setVisualTransformOverride(const WebFloatRect& area, float scale) | 
| +{ | 
| + if (!m_visualTransformOverride) | 
| + m_visualTransformOverride = VisualTransformOverride(); | 
| + | 
| + m_visualTransformOverride->area = area; | 
| + m_visualTransformOverride->scale = scale; | 
| + | 
| + // Ensure that all content inside the area is painted. | 
| + if (m_webViewImpl->mainFrameImpl()) | 
| + m_webViewImpl->mainFrameImpl()->frameView()->setVisibleContentRectForPainting(enclosingIntRect(area)); | 
| 
chrishtr
2016/08/12 20:56:22
Why can't this be accomplished by changing the wid
 
Eric Seckler
2016/08/12 21:37:53
I don't think width&height would suffice, since we
 
chrishtr
2016/08/12 21:41:36
Why would you want it to be different than the cur
 
Eric Seckler
2016/08/12 21:55:36
We want to record+render only the screenshot area,
 
chrishtr
2016/08/12 22:03:43
Is the objection to scrolling to the desired area
 
Eric Seckler
2016/08/12 22:15:46
Correct. Javascript can listen for scroll events a
 | 
| + | 
| + // 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_visualTransformOverride->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::clearVisualTransformOverride() | 
| +{ | 
| + if (!m_visualTransformOverride) | 
| + return; | 
| + | 
| + bool originalMasking = m_visualTransformOverride->originalVisualViewportMasking; | 
| + m_visualTransformOverride = WTF::nullopt; | 
| + | 
| + // Restore original state. | 
| + if (m_webViewImpl->mainFrameImpl()) | 
| + m_webViewImpl->mainFrameImpl()->frameView()->resetVisibleContentRectForPainting(); | 
| + GraphicsLayer* containerLayer = m_webViewImpl->page()->frameHost().visualViewport().containerLayer(); | 
| + if (containerLayer) | 
| + containerLayer->setMasksToBounds(originalMasking); | 
| + updateRootLayerTransform(); | 
| +} | 
| + | 
| +void DevToolsEmulator::mainFrameScrollOrScaleChanged() | 
| +{ | 
| + // Visual transform override has to take current page scale and scroll | 
| + // offset into account. Update the transform if override is active. | 
| + if (m_visualTransformOverride) | 
| + 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::applyVisualTransformOverride(TransformationMatrix* transform) | 
| +{ | 
| + if (!m_visualTransformOverride) | 
| + return; | 
| + | 
| + // Transform operations follow in reverse application. | 
| + // Last, scale positioned area according to override. | 
| + transform->scale(m_visualTransformOverride->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_visualTransformOverride->area.x + scrollX, | 
| + -m_visualTransformOverride->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 | 
| + // visual transform override. | 
| + applyVisualTransformOverride(&transform); | 
| + applyDeviceEmulationTransform(&transform); | 
| + | 
| + m_webViewImpl->setRootLayerTransform(transform); | 
| +} | 
| + | 
| void DevToolsEmulator::setTouchEventEmulationEnabled(bool enabled) | 
| { | 
| if (m_touchEventEmulationEnabled == enabled) |