summaryrefslogtreecommitdiffstats
path: root/content/renderer/render_widget.cc
diff options
context:
space:
mode:
Diffstat (limited to 'content/renderer/render_widget.cc')
-rw-r--r--content/renderer/render_widget.cc490
1 files changed, 355 insertions, 135 deletions
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index d3d5433..592a57c 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -41,7 +41,6 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/context_menu_params.h"
#include "content/renderer/cursor_utils.h"
-#include "content/renderer/devtools/render_widget_screen_metrics_emulator.h"
#include "content/renderer/external_popup_menu.h"
#include "content/renderer/gpu/compositor_output_surface.h"
#include "content/renderer/gpu/delegated_compositor_output_surface.h"
@@ -203,6 +202,244 @@ content::RenderWidgetInputHandlerDelegate* GetRenderWidgetInputHandlerDelegate(
namespace content {
+// RenderWidget::ScreenMetricsEmulator ----------------------------------------
+
+class RenderWidget::ScreenMetricsEmulator {
+ public:
+ ScreenMetricsEmulator(
+ RenderWidget* widget,
+ const WebDeviceEmulationParams& params);
+ virtual ~ScreenMetricsEmulator();
+
+ // Scale and offset used to convert between host coordinates
+ // and webwidget coordinates.
+ float scale() { return scale_; }
+ gfx::PointF offset() { return offset_; }
+ gfx::Rect applied_widget_rect() const { return applied_widget_rect_; }
+ gfx::Rect original_screen_rect() const { return original_view_screen_rect_; }
+ const WebScreenInfo& original_screen_info() { return original_screen_info_; }
+
+ void ChangeEmulationParams(
+ const WebDeviceEmulationParams& params);
+
+ // The following methods alter handlers' behavior for messages related to
+ // widget size and position.
+ void OnResizeMessage(const ResizeParams& params);
+ void OnUpdateScreenRectsMessage(const gfx::Rect& view_screen_rect,
+ const gfx::Rect& window_screen_rect);
+ void OnShowContextMenu(ContextMenuParams* params);
+ gfx::Rect AdjustValidationMessageAnchor(const gfx::Rect& anchor);
+
+ private:
+ void Reapply();
+ void Apply(bool top_controls_shrink_blink_size,
+ float top_controls_height,
+ gfx::Rect resizer_rect,
+ bool is_fullscreen_granted,
+ blink::WebDisplayMode display_mode);
+
+ RenderWidget* widget_;
+
+ // Parameters as passed by RenderWidget::EnableScreenMetricsEmulation.
+ WebDeviceEmulationParams params_;
+
+ // The computed scale and offset used to fit widget into browser window.
+ float scale_;
+ gfx::PointF offset_;
+
+ // Widget rect as passed to webwidget.
+ gfx::Rect applied_widget_rect_;
+
+ // Original values to restore back after emulation ends.
+ gfx::Size original_size_;
+ gfx::Size original_physical_backing_size_;
+ gfx::Size original_visible_viewport_size_;
+ blink::WebScreenInfo original_screen_info_;
+ gfx::Rect original_view_screen_rect_;
+ gfx::Rect original_window_screen_rect_;
+};
+
+RenderWidget::ScreenMetricsEmulator::ScreenMetricsEmulator(
+ RenderWidget* widget,
+ const WebDeviceEmulationParams& params)
+ : widget_(widget),
+ params_(params),
+ scale_(1.f) {
+ original_size_ = widget_->size_;
+ original_physical_backing_size_ = widget_->physical_backing_size_;
+ original_visible_viewport_size_ = widget_->visible_viewport_size_;
+ original_screen_info_ = widget_->screen_info_;
+ original_view_screen_rect_ = widget_->view_screen_rect_;
+ original_window_screen_rect_ = widget_->window_screen_rect_;
+ Apply(widget_->top_controls_shrink_blink_size_,
+ widget_->top_controls_height_,
+ widget_->resizer_rect_,
+ widget_->is_fullscreen_granted_,
+ widget_->display_mode_);
+}
+
+RenderWidget::ScreenMetricsEmulator::~ScreenMetricsEmulator() {
+ widget_->screen_info_ = original_screen_info_;
+
+ widget_->SetDeviceScaleFactor(original_screen_info_.deviceScaleFactor);
+ widget_->SetScreenMetricsEmulationParameters(false, params_);
+ widget_->view_screen_rect_ = original_view_screen_rect_;
+ widget_->window_screen_rect_ = original_window_screen_rect_;
+ widget_->Resize(original_size_,
+ original_physical_backing_size_,
+ widget_->top_controls_shrink_blink_size_,
+ widget_->top_controls_height_,
+ original_visible_viewport_size_,
+ widget_->resizer_rect_,
+ widget_->is_fullscreen_granted_,
+ widget_->display_mode_,
+ NO_RESIZE_ACK);
+}
+
+void RenderWidget::ScreenMetricsEmulator::ChangeEmulationParams(
+ const WebDeviceEmulationParams& params) {
+ params_ = params;
+ Reapply();
+}
+
+void RenderWidget::ScreenMetricsEmulator::Reapply() {
+ Apply(widget_->top_controls_shrink_blink_size_,
+ widget_->top_controls_height_,
+ widget_->resizer_rect_,
+ widget_->is_fullscreen_granted_,
+ widget_->display_mode_);
+}
+
+void RenderWidget::ScreenMetricsEmulator::Apply(
+ bool top_controls_shrink_blink_size,
+ float top_controls_height,
+ gfx::Rect resizer_rect,
+ bool is_fullscreen_granted,
+ blink::WebDisplayMode display_mode) {
+ applied_widget_rect_.set_size(gfx::Size(params_.viewSize));
+ if (!applied_widget_rect_.width())
+ applied_widget_rect_.set_width(original_size_.width());
+ if (!applied_widget_rect_.height())
+ applied_widget_rect_.set_height(original_size_.height());
+
+ if (params_.fitToView && !original_size_.IsEmpty()) {
+ int original_width = std::max(original_size_.width(), 1);
+ int original_height = std::max(original_size_.height(), 1);
+ float width_ratio =
+ static_cast<float>(applied_widget_rect_.width()) / original_width;
+ float height_ratio =
+ static_cast<float>(applied_widget_rect_.height()) / original_height;
+ float ratio = std::max(1.0f, std::max(width_ratio, height_ratio));
+ scale_ = 1.f / ratio;
+
+ // Center emulated view inside available view space.
+ offset_.set_x(
+ (original_size_.width() - scale_ * applied_widget_rect_.width()) / 2);
+ offset_.set_y(
+ (original_size_.height() - scale_ * applied_widget_rect_.height()) / 2);
+ } else {
+ scale_ = params_.scale;
+ offset_.SetPoint(params_.offset.x, params_.offset.y);
+ if (!params_.viewSize.width && !params_.viewSize.height && scale_) {
+ applied_widget_rect_.set_size(gfx::ScaleToRoundedSize(
+ original_size_, 1.f / scale_));
+ }
+ }
+
+ if (params_.screenPosition == WebDeviceEmulationParams::Desktop) {
+ applied_widget_rect_.set_origin(original_view_screen_rect_.origin());
+ widget_->screen_info_.rect = original_screen_info_.rect;
+ widget_->screen_info_.availableRect = original_screen_info_.availableRect;
+ widget_->window_screen_rect_ = original_window_screen_rect_;
+ } else {
+ applied_widget_rect_.set_origin(params_.viewPosition);
+ gfx::Rect screen_rect = applied_widget_rect_;
+ if (!params_.screenSize.isEmpty()) {
+ screen_rect =
+ gfx::Rect(0, 0, params_.screenSize.width, params_.screenSize.height);
+ }
+ widget_->screen_info_.rect = screen_rect;
+ widget_->screen_info_.availableRect = screen_rect;
+ widget_->window_screen_rect_ = applied_widget_rect_;
+ }
+
+ float applied_device_scale_factor = params_.deviceScaleFactor ?
+ params_.deviceScaleFactor : original_screen_info_.deviceScaleFactor;
+ widget_->screen_info_.deviceScaleFactor = applied_device_scale_factor;
+
+ // Pass three emulation parameters to the blink side:
+ // - we keep the real device scale factor in compositor to produce sharp image
+ // even when emulating different scale factor;
+ // - in order to fit into view, WebView applies offset and scale to the
+ // root layer.
+ blink::WebDeviceEmulationParams modified_params = params_;
+ modified_params.deviceScaleFactor = original_screen_info_.deviceScaleFactor;
+ modified_params.offset = blink::WebFloatPoint(offset_.x(), offset_.y());
+ modified_params.scale = scale_;
+ widget_->SetScreenMetricsEmulationParameters(true, modified_params);
+
+ widget_->SetDeviceScaleFactor(applied_device_scale_factor);
+ widget_->view_screen_rect_ = applied_widget_rect_;
+
+ gfx::Size physical_backing_size = gfx::ScaleToCeiledSize(
+ original_size_, original_screen_info_.deviceScaleFactor);
+ widget_->Resize(applied_widget_rect_.size(),
+ physical_backing_size,
+ top_controls_shrink_blink_size,
+ top_controls_height,
+ applied_widget_rect_.size(),
+ resizer_rect,
+ is_fullscreen_granted,
+ display_mode,
+ NO_RESIZE_ACK);
+}
+
+void RenderWidget::ScreenMetricsEmulator::OnResizeMessage(
+ const ResizeParams& params) {
+ bool need_ack = params.new_size != original_size_ &&
+ !params.new_size.IsEmpty() && !params.physical_backing_size.IsEmpty();
+ original_size_ = params.new_size;
+ original_physical_backing_size_ = params.physical_backing_size;
+ original_screen_info_ = params.screen_info;
+ original_visible_viewport_size_ = params.visible_viewport_size;
+ Apply(params.top_controls_shrink_blink_size,
+ params.top_controls_height,
+ params.resizer_rect,
+ params.is_fullscreen_granted,
+ params.display_mode);
+
+ if (need_ack) {
+ widget_->set_next_paint_is_resize_ack();
+ if (widget_->compositor_)
+ widget_->compositor_->SetNeedsRedrawRect(gfx::Rect(widget_->size_));
+ }
+}
+
+void RenderWidget::ScreenMetricsEmulator::OnUpdateScreenRectsMessage(
+ const gfx::Rect& view_screen_rect,
+ const gfx::Rect& window_screen_rect) {
+ original_view_screen_rect_ = view_screen_rect;
+ original_window_screen_rect_ = window_screen_rect;
+ if (params_.screenPosition == WebDeviceEmulationParams::Desktop)
+ Reapply();
+}
+
+void RenderWidget::ScreenMetricsEmulator::OnShowContextMenu(
+ ContextMenuParams* params) {
+ params->x *= scale_;
+ params->x += offset_.x();
+ params->y *= scale_;
+ params->y += offset_.y();
+}
+
+gfx::Rect RenderWidget::ScreenMetricsEmulator::AdjustValidationMessageAnchor(
+ const gfx::Rect& anchor) {
+ gfx::Rect scaled = gfx::ScaleToEnclosedRect(anchor, scale_);
+ scaled.set_x(scaled.x() + offset_.x());
+ scaled.set_y(scaled.y() + offset_.y());
+ return scaled;
+}
+
// RenderWidget ---------------------------------------------------------------
RenderWidget::RenderWidget(CompositorDependencies* compositor_deps,
@@ -416,7 +653,7 @@ void RenderWidget::WasSwappedOut() {
}
void RenderWidget::SetPopupOriginAdjustmentsForEmulation(
- RenderWidgetScreenMetricsEmulator* emulator) {
+ ScreenMetricsEmulator* emulator) {
popup_origin_scale_for_emulation_ = emulator->scale();
popup_view_origin_for_emulation_ = emulator->applied_widget_rect().origin();
popup_screen_origin_for_emulation_ = gfx::Point(
@@ -432,10 +669,16 @@ gfx::Rect RenderWidget::AdjustValidationMessageAnchor(const gfx::Rect& anchor) {
return anchor;
}
+void RenderWidget::SetScreenMetricsEmulationParameters(
+ bool enabled,
+ const blink::WebDeviceEmulationParams& params) {
+ // This is only supported in RenderView.
+ NOTREACHED();
+}
+
#if defined(OS_MACOSX) || defined(OS_ANDROID)
void RenderWidget::SetExternalPopupOriginAdjustmentsForEmulation(
- ExternalPopupMenu* popup,
- RenderWidgetScreenMetricsEmulator* emulator) {
+ ExternalPopupMenu* popup, ScreenMetricsEmulator* emulator) {
popup->SetOriginScaleAndOffsetForEmulation(
emulator->scale(), emulator->offset());
}
@@ -502,21 +745,97 @@ bool RenderWidget::Send(IPC::Message* message) {
return RenderThread::Get()->Send(message);
}
+void RenderWidget::Resize(const gfx::Size& new_size,
+ const gfx::Size& physical_backing_size,
+ bool top_controls_shrink_blink_size,
+ float top_controls_height,
+ const gfx::Size& visible_viewport_size,
+ const gfx::Rect& resizer_rect,
+ bool is_fullscreen_granted,
+ blink::WebDisplayMode display_mode,
+ const ResizeAck resize_ack) {
+ if (resizing_mode_selector_->NeverUsesSynchronousResize()) {
+ // A resize ack shouldn't be requested if we have not ACK'd the previous
+ // one.
+ DCHECK(resize_ack != SEND_RESIZE_ACK || !next_paint_is_resize_ack());
+ DCHECK(resize_ack == SEND_RESIZE_ACK || resize_ack == NO_RESIZE_ACK);
+ }
+
+ // Ignore this during shutdown.
+ if (!webwidget_)
+ return;
+
+ if (compositor_)
+ compositor_->setViewportSize(physical_backing_size);
+
+ bool resized = size_ != new_size ||
+ physical_backing_size_ != physical_backing_size;
+
+ size_ = new_size;
+ physical_backing_size_ = physical_backing_size;
+
+ top_controls_shrink_blink_size_ = top_controls_shrink_blink_size;
+ top_controls_height_ = top_controls_height;
+ visible_viewport_size_ = visible_viewport_size;
+ resizer_rect_ = resizer_rect;
+
+ // NOTE: We may have entered fullscreen mode without changing our size.
+ bool fullscreen_change = is_fullscreen_granted_ != is_fullscreen_granted;
+ is_fullscreen_granted_ = is_fullscreen_granted;
+ display_mode_ = display_mode;
+
+ webwidget_->setTopControlsHeight(top_controls_height,
+ top_controls_shrink_blink_size_);
+
+ if (resized) {
+ gfx::Size new_widget_size =
+ IsUseZoomForDSFEnabled() ? physical_backing_size_ : size_;
+ // When resizing, we want to wait to paint before ACK'ing the resize. This
+ // ensures that we only resize as fast as we can paint. We only need to
+ // send an ACK if we are resized to a non-empty rect.
+ webwidget_->resize(new_widget_size);
+ }
+ WebSize visual_viewport_size;
+
+ if (IsUseZoomForDSFEnabled()) {
+ visual_viewport_size =
+ gfx::ScaleToCeiledSize(visible_viewport_size, device_scale_factor_);
+ } else {
+ visual_viewport_size = visible_viewport_size_;
+ }
+
+ webwidget()->resizeVisualViewport(visual_viewport_size);
+
+ if (new_size.IsEmpty() || physical_backing_size.IsEmpty()) {
+ // In this case there is no paint/composite and therefore no
+ // ViewHostMsg_UpdateRect to send the resize ack with. We'd need to send the
+ // ack through a fake ViewHostMsg_UpdateRect or a different message.
+ DCHECK_EQ(resize_ack, NO_RESIZE_ACK);
+ }
+
+ // Send the Resize_ACK flag once we paint again if requested.
+ if (resize_ack == SEND_RESIZE_ACK)
+ set_next_paint_is_resize_ack();
+
+ if (fullscreen_change)
+ DidToggleFullscreen();
+
+ // If a resize ack is requested and it isn't set-up, then no more resizes will
+ // come in and in general things will go wrong.
+ DCHECK(resize_ack != SEND_RESIZE_ACK || next_paint_is_resize_ack());
+}
+
void RenderWidget::SetWindowRectSynchronously(
const gfx::Rect& new_window_rect) {
- ResizeParams params;
- params.new_size = new_window_rect.size();
- params.physical_backing_size =
- gfx::ScaleToCeiledSize(new_window_rect.size(), device_scale_factor_);
- params.top_controls_shrink_blink_size = top_controls_shrink_blink_size_;
- params.top_controls_height = top_controls_height_;
- params.visible_viewport_size = new_window_rect.size();
- params.resizer_rect = gfx::Rect();
- params.is_fullscreen_granted = is_fullscreen_granted_;
- params.display_mode = display_mode_;
- params.needs_resize_ack = false;
- Resize(params);
-
+ Resize(new_window_rect.size(),
+ gfx::ScaleToCeiledSize(new_window_rect.size(), device_scale_factor_),
+ top_controls_shrink_blink_size_,
+ top_controls_height_,
+ new_window_rect.size(),
+ gfx::Rect(),
+ is_fullscreen_granted_,
+ display_mode_,
+ NO_RESIZE_ACK);
view_screen_rect_ = new_window_rect;
window_screen_rect_ = new_window_rect;
if (!did_show_)
@@ -562,14 +881,24 @@ void RenderWidget::OnResize(const ResizeParams& params) {
return;
if (screen_metrics_emulator_) {
- screen_metrics_emulator_->OnResize(params);
+ screen_metrics_emulator_->OnResizeMessage(params);
return;
}
bool orientation_changed =
screen_info_.orientationAngle != params.screen_info.orientationAngle;
- Resize(params);
+ screen_info_ = params.screen_info;
+ SetDeviceScaleFactor(screen_info_.deviceScaleFactor);
+ Resize(params.new_size,
+ params.physical_backing_size,
+ params.top_controls_shrink_blink_size,
+ params.top_controls_height,
+ params.visible_viewport_size,
+ params.resizer_rect,
+ params.is_fullscreen_granted,
+ params.display_mode,
+ params.needs_resize_ack ? SEND_RESIZE_ACK : NO_RESIZE_ACK);
if (orientation_changed)
OnOrientationChange();
@@ -577,23 +906,10 @@ void RenderWidget::OnResize(const ResizeParams& params) {
void RenderWidget::OnEnableDeviceEmulation(
const blink::WebDeviceEmulationParams& params) {
- if (!screen_metrics_emulator_) {
- ResizeParams resize_params;
- resize_params.new_size = size_;
- resize_params.physical_backing_size = physical_backing_size_;
- resize_params.visible_viewport_size = visible_viewport_size_;
- resize_params.screen_info = screen_info_;
- resize_params.top_controls_shrink_blink_size =
- top_controls_shrink_blink_size_;
- resize_params.top_controls_height = top_controls_height_;
- resize_params.resizer_rect = resizer_rect_;
- resize_params.is_fullscreen_granted = is_fullscreen_granted_;
- resize_params.display_mode = display_mode_;
- screen_metrics_emulator_.reset(new RenderWidgetScreenMetricsEmulator(
- this, params, resize_params, view_screen_rect_, window_screen_rect_));
- } else {
+ if (!screen_metrics_emulator_)
+ screen_metrics_emulator_.reset(new ScreenMetricsEmulator(this, params));
+ else
screen_metrics_emulator_->ChangeEmulationParams(params);
- }
}
void RenderWidget::OnDisableDeviceEmulation() {
@@ -1038,103 +1354,6 @@ bool RenderWidget::WillHandleMouseEvent(const blink::WebMouseEvent& event) {
}
///////////////////////////////////////////////////////////////////////////////
-// RenderWidgetScreenMetricsDelegate
-
-void RenderWidget::Redraw() {
- set_next_paint_is_resize_ack();
- if (compositor_)
- compositor_->SetNeedsRedrawRect(gfx::Rect(size_));
-}
-
-void RenderWidget::Resize(const ResizeParams& params) {
- screen_info_ = params.screen_info;
- SetDeviceScaleFactor(screen_info_.deviceScaleFactor);
-
- if (resizing_mode_selector_->NeverUsesSynchronousResize()) {
- // A resize ack shouldn't be requested if we have not ACK'd the previous
- // one.
- DCHECK(!params.needs_resize_ack || !next_paint_is_resize_ack());
- }
-
- // Ignore this during shutdown.
- if (!webwidget_)
- return;
-
- if (compositor_)
- compositor_->setViewportSize(params.physical_backing_size);
-
- bool resized = size_ != params.new_size ||
- physical_backing_size_ != params.physical_backing_size;
-
- size_ = params.new_size;
- physical_backing_size_ = params.physical_backing_size;
-
- top_controls_shrink_blink_size_ = params.top_controls_shrink_blink_size;
- top_controls_height_ = params.top_controls_height;
- visible_viewport_size_ = params.visible_viewport_size;
- resizer_rect_ = params.resizer_rect;
-
- // NOTE: We may have entered fullscreen mode without changing our size.
- bool fullscreen_change =
- is_fullscreen_granted_ != params.is_fullscreen_granted;
- is_fullscreen_granted_ = params.is_fullscreen_granted;
- display_mode_ = params.display_mode;
-
- webwidget_->setTopControlsHeight(params.top_controls_height,
- top_controls_shrink_blink_size_);
-
- if (resized) {
- gfx::Size new_widget_size =
- IsUseZoomForDSFEnabled() ? physical_backing_size_ : size_;
- // When resizing, we want to wait to paint before ACK'ing the resize. This
- // ensures that we only resize as fast as we can paint. We only need to
- // send an ACK if we are resized to a non-empty rect.
- webwidget_->resize(new_widget_size);
- }
- WebSize visual_viewport_size;
-
- if (IsUseZoomForDSFEnabled()) {
- visual_viewport_size = gfx::ScaleToCeiledSize(params.visible_viewport_size,
- device_scale_factor_);
- } else {
- visual_viewport_size = visible_viewport_size_;
- }
-
- webwidget()->resizeVisualViewport(visual_viewport_size);
-
- if (params.new_size.IsEmpty() || params.physical_backing_size.IsEmpty()) {
- // In this case there is no paint/composite and therefore no
- // ViewHostMsg_UpdateRect to send the resize ack with. We'd need to send the
- // ack through a fake ViewHostMsg_UpdateRect or a different message.
- DCHECK(!params.needs_resize_ack);
- }
-
- // Send the Resize_ACK flag once we paint again if requested.
- if (params.needs_resize_ack)
- set_next_paint_is_resize_ack();
-
- if (fullscreen_change)
- DidToggleFullscreen();
-
- // If a resize ack is requested and it isn't set-up, then no more resizes will
- // come in and in general things will go wrong.
- DCHECK(!params.needs_resize_ack || next_paint_is_resize_ack());
-}
-
-void RenderWidget::SetScreenMetricsEmulationParameters(
- bool enabled,
- const blink::WebDeviceEmulationParams& params) {
- // This is only supported in RenderView.
- NOTREACHED();
-}
-
-void RenderWidget::SetScreenRects(const gfx::Rect& view_screen_rect,
- const gfx::Rect& window_screen_rect) {
- view_screen_rect_ = view_screen_rect;
- window_screen_rect_ = window_screen_rect;
-}
-
-///////////////////////////////////////////////////////////////////////////////
// WebWidgetClient
void RenderWidget::didAutoResize(const WebSize& new_size) {
@@ -1498,10 +1717,11 @@ void RenderWidget::OnSetTextDirection(WebTextDirection direction) {
void RenderWidget::OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
const gfx::Rect& window_screen_rect) {
if (screen_metrics_emulator_) {
- screen_metrics_emulator_->OnUpdateScreenRects(view_screen_rect,
- window_screen_rect);
+ screen_metrics_emulator_->OnUpdateScreenRectsMessage(
+ view_screen_rect, window_screen_rect);
} else {
- SetScreenRects(view_screen_rect, window_screen_rect);
+ view_screen_rect_ = view_screen_rect;
+ window_screen_rect_ = window_screen_rect;
}
Send(new ViewHostMsg_UpdateScreenRects_ACK(routing_id()));
}