Commit 043ee673 authored by Dmitry Gozman's avatar Dmitry Gozman Committed by Commit Bot

[DevTools] Control+drag to capture area screenshot in Inspect Mode

This user action issues Overlay.screenshotRequested notification.
We can split this away from inspect mode, but that needs more UI surface.

Bug: 749252
Change-Id: I518c31d943179650fb8517a4c9d1bd7b677e0dbc
Reviewed-on: https://chromium-review.googlesource.com/587396
Commit-Queue: Dmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#490608}
parent 73b3e2da
......@@ -28,6 +28,7 @@
#include "core/inspector/InspectorOverlayAgent.h"
#include <algorithm>
#include <memory>
#include "bindings/core/v8/ScriptController.h"
......@@ -551,9 +552,9 @@ bool InspectorOverlayAgent::HandleInputEvent(const WebInputEvent& input_event) {
if (mouse_event.GetType() == WebInputEvent::kMouseMove)
handled = HandleMouseMove(mouse_event);
else if (mouse_event.GetType() == WebInputEvent::kMouseDown)
handled = HandleMouseDown();
handled = HandleMouseDown(mouse_event);
else if (mouse_event.GetType() == WebInputEvent::kMouseUp)
handled = HandleMouseUp();
handled = HandleMouseUp(mouse_event);
if (handled)
return true;
......@@ -697,6 +698,7 @@ void InspectorOverlayAgent::RebuildOverlayPage() {
DrawQuadHighlight();
DrawPausedInDebuggerMessage();
DrawViewSize();
DrawScreenshotBorder();
}
static std::unique_ptr<protocol::DictionaryValue> BuildObjectForSize(
......@@ -770,6 +772,22 @@ void InspectorOverlayAgent::DrawViewSize() {
EvaluateInOverlay("drawViewSize", "");
}
void InspectorOverlayAgent::DrawScreenshotBorder() {
if (!screenshot_mode_)
return;
VisualViewport& visual_viewport =
frame_impl_->GetFrame()->GetPage()->GetVisualViewport();
IntPoint p1 = visual_viewport.RootFrameToViewport(screenshot_anchor_);
IntPoint p2 = visual_viewport.RootFrameToViewport(screenshot_position_);
std::unique_ptr<protocol::DictionaryValue> data =
protocol::DictionaryValue::create();
data->setInteger("x1", p1.X());
data->setInteger("y1", p1.Y());
data->setInteger("x2", p2.X());
data->setInteger("y2", p2.Y());
EvaluateInOverlay("drawScreenshotBorder", std::move(data));
}
float InspectorOverlayAgent::WindowToViewportScale() const {
LocalFrame* frame = frame_impl_->GetFrame();
if (!frame)
......@@ -944,6 +962,7 @@ void InspectorOverlayAgent::ClearInternal() {
resize_timer_active_ = false;
paused_in_debugger_message_ = String();
inspect_mode_ = kNotSearching;
screenshot_mode_ = false;
timer_.Stop();
page_overlay_.reset();
InnerHideHighlight();
......@@ -971,6 +990,21 @@ bool InspectorOverlayAgent::HandleMouseMove(const WebMouseEvent& event) {
if (!ShouldSearchForNode())
return false;
if (event.GetModifiers() & WebInputEvent::kControlKey) {
InnerHideHighlight();
hovered_node_for_inspect_mode_.Clear();
if (screenshot_mode_) {
screenshot_position_ = RoundedIntPoint(event.PositionInRootFrame());
ScheduleUpdate();
}
return true;
}
if (screenshot_mode_) {
screenshot_mode_ = false;
ScheduleUpdate();
}
LocalFrame* frame = frame_impl_->GetFrame();
if (!frame || !frame->View() || frame->ContentLayoutItem().IsNull())
return false;
......@@ -1019,11 +1053,23 @@ bool InspectorOverlayAgent::HandleMouseMove(const WebMouseEvent& event) {
return true;
}
bool InspectorOverlayAgent::HandleMouseDown() {
bool InspectorOverlayAgent::HandleMouseDown(const WebMouseEvent& event) {
swallow_next_mouse_up_ = false;
screenshot_mode_ = false;
if (!ShouldSearchForNode())
return false;
if ((event.GetModifiers() & WebInputEvent::kControlKey) &&
(event.GetModifiers() & WebInputEvent::kLeftButtonDown)) {
InnerHideHighlight();
hovered_node_for_inspect_mode_.Clear();
screenshot_mode_ = true;
screenshot_anchor_ = RoundedIntPoint(event.PositionInRootFrame());
screenshot_position_ = screenshot_anchor_;
ScheduleUpdate();
return true;
}
if (hovered_node_for_inspect_mode_) {
swallow_next_mouse_up_ = true;
Inspect(hovered_node_for_inspect_mode_.Get());
......@@ -1033,7 +1079,30 @@ bool InspectorOverlayAgent::HandleMouseDown() {
return false;
}
bool InspectorOverlayAgent::HandleMouseUp() {
bool InspectorOverlayAgent::HandleMouseUp(const WebMouseEvent& event) {
if (screenshot_mode_) {
screenshot_mode_ = false;
float scale = 1.0f;
IntPoint p1 = screenshot_anchor_;
IntPoint p2 = screenshot_position_;
if (LocalFrame* frame = frame_impl_->GetFrame()) {
scale = frame->GetPage()->PageScaleFactor();
p1 = frame->View()->RootFrameToContents(p1);
p2 = frame->View()->RootFrameToContents(p2);
}
int min_x = std::min(p1.X(), p2.X());
int max_x = std::max(p1.X(), p2.X());
int min_y = std::min(p1.Y(), p2.Y());
int max_y = std::max(p1.Y(), p2.Y());
GetFrontend()->screenshotRequested(protocol::Page::Viewport::create()
.setX(min_x)
.setY(min_y)
.setWidth(max_x - min_x)
.setHeight(max_y - min_y)
.setScale(scale)
.build());
return true;
}
if (swallow_next_mouse_up_) {
swallow_next_mouse_up_ = false;
return true;
......@@ -1119,6 +1188,7 @@ Response InspectorOverlayAgent::SetSearchingForNode(
Maybe<protocol::Overlay::HighlightConfig> highlight_inspector_object) {
if (search_mode == kNotSearching) {
inspect_mode_ = search_mode;
screenshot_mode_ = false;
ScheduleUpdate();
hovered_node_for_inspect_mode_.Clear();
InnerHideHighlight();
......
......@@ -146,6 +146,7 @@ class CORE_EXPORT InspectorOverlayAgent final
void DrawQuadHighlight();
void DrawPausedInDebuggerMessage();
void DrawViewSize();
void DrawScreenshotBorder();
float WindowToViewportScale() const;
......@@ -163,8 +164,8 @@ class CORE_EXPORT InspectorOverlayAgent final
void ClearInternal();
void UpdateAllLifecyclePhases();
bool HandleMouseDown();
bool HandleMouseUp();
bool HandleMouseDown(const WebMouseEvent&);
bool HandleMouseUp(const WebMouseEvent&);
bool HandleGestureEvent(const WebGestureEvent&);
bool HandleTouchEvent(const WebTouchEvent&);
bool HandleMouseMove(const WebMouseEvent&);
......@@ -219,6 +220,9 @@ class CORE_EXPORT InspectorOverlayAgent final
SearchMode inspect_mode_;
std::unique_ptr<InspectorHighlightConfig> inspect_mode_highlight_config_;
int backend_node_id_to_inspect_;
bool screenshot_mode_ = false;
IntPoint screenshot_anchor_;
IntPoint screenshot_position_;
};
} // namespace blink
......
......@@ -758,6 +758,30 @@ function drawHighlight(highlight, context)
return { bounds: bounds };
}
function drawScreenshotBorder(rect)
{
var context = window.context;
context.save();
context.fillStyle = "rgba(0, 0, 0, 0.2)";
context.beginPath();
context.moveTo(rect.x1 - 0.5, rect.y1 - 0.5);
context.lineTo(rect.x1 - 0.5, rect.y2 + 0.5);
context.lineTo(rect.x2 + 0.5, rect.y2 + 0.5);
context.lineTo(rect.x2 + 0.5, rect.y1 - 0.5);
context.lineTo(rect.x1 - 0.5, rect.y1 - 0.5);
context.fill();
context.strokeStyle = "rgba(255, 255, 255, 0.9)";
context.lineWidth = 1;
context.beginPath();
context.moveTo(rect.x1 - 0.5, rect.y1 - 0.5);
context.lineTo(rect.x1 - 0.5, rect.y2 + 0.5);
context.lineTo(rect.x2 + 0.5, rect.y2 + 0.5);
context.lineTo(rect.x2 + 0.5, rect.y1 - 0.5);
context.lineTo(rect.x1 - 0.5, rect.y1 - 0.5);
context.stroke();
context.restore();
}
function setPlatform(platform)
{
window.platform = platform;
......
......@@ -882,6 +882,13 @@
"parameters": [
{ "name": "backendNodeId", "$ref": "DOM.BackendNodeId", "description": "Id of the node to inspect." }
]
},
{
"name": "screenshotRequested",
"description": "Fired when user asks to capture screenshot of some area on the page.",
"parameters": [
{ "name": "viewport", "$ref": "Page.Viewport", "description": "Viewport to capture, in CSS." }
]
}
]
},
......
......@@ -34,6 +34,9 @@ Elements.InspectElementModeController = class {
this._toggleSearchAction = UI.actionRegistry.action('elements.toggle-element-search');
this._mode = Protocol.Overlay.InspectMode.None;
SDK.targetManager.addEventListener(SDK.TargetManager.Events.SuspendStateChanged, this._suspendStateChanged, this);
SDK.targetManager.addModelListener(
SDK.OverlayModel, SDK.OverlayModel.Events.ScreenshotRequested,
() => this._setMode(Protocol.Overlay.InspectMode.None));
SDK.targetManager.observeModels(SDK.OverlayModel, this);
}
......
......@@ -18,6 +18,8 @@ Emulation.DeviceModeWrapper = class extends UI.VBox {
var model = self.singleton(Emulation.DeviceModeModel);
this._showDeviceModeSetting = model.enabledSetting();
this._showDeviceModeSetting.addChangeListener(this._update.bind(this, false));
SDK.targetManager.addModelListener(
SDK.OverlayModel, SDK.OverlayModel.Events.ScreenshotRequested, this._screenshotRequestedFromOverlay, this);
this._update(true);
}
......@@ -43,6 +45,14 @@ Emulation.DeviceModeWrapper = class extends UI.VBox {
return true;
}
/**
* @param {!Common.Event} event
*/
_screenshotRequestedFromOverlay(event) {
var clip = /** @type {!Protocol.Page.Viewport} */ (event.data);
this._captureScreenshot(false, clip);
}
/**
* @param {boolean} force
*/
......
......@@ -231,6 +231,14 @@ SDK.OverlayModel = class extends SDK.SDKModel {
var deferredNode = new SDK.DeferredDOMNode(this.target(), backendNodeId);
this.dispatchEventToListeners(SDK.OverlayModel.Events.InspectNodeRequested, deferredNode);
}
/**
* @override
* @param {!Protocol.Page.Viewport} viewport
*/
screenshotRequested(viewport) {
this.dispatchEventToListeners(SDK.OverlayModel.Events.ScreenshotRequested, viewport);
}
};
SDK.SDKModel.register(SDK.OverlayModel, SDK.Target.Capability.DOM, true);
......@@ -240,6 +248,7 @@ SDK.OverlayModel.Events = {
InspectModeWillBeToggled: Symbol('InspectModeWillBeToggled'),
HighlightNodeRequested: Symbol('HighlightNodeRequested'),
InspectNodeRequested: Symbol('InspectNodeRequested'),
ScreenshotRequested: Symbol('ScreenshotRequested'),
};
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment