Chromium Code Reviews| Index: content/renderer/render_widget.cc |
| diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc |
| index 95a403b8d92f4359a32ad94bf61551872dd60c1f..181afd9593a5820e2ad07e8214fcbf56ee9b2c6c 100644 |
| --- a/content/renderer/render_widget.cc |
| +++ b/content/renderer/render_widget.cc |
| @@ -26,6 +26,7 @@ |
| #include "content/common/view_messages.h" |
| #include "content/public/common/content_switches.h" |
| #include "content/renderer/cursor_utils.h" |
| +#include "content/renderer/external_popup_menu.h" |
| #include "content/renderer/gpu/compositor_output_surface.h" |
| #include "content/renderer/gpu/compositor_software_output_device.h" |
| #include "content/renderer/gpu/delegated_compositor_output_surface.h" |
| @@ -53,7 +54,7 @@ |
| #include "third_party/WebKit/public/web/WebScreenInfo.h" |
| #include "third_party/skia/include/core/SkShader.h" |
| #include "ui/base/ui_base_switches.h" |
| -#include "ui/gfx/point.h" |
| +#include "ui/gfx/point_conversions.h" |
| #include "ui/gfx/rect_conversions.h" |
| #include "ui/gfx/size_conversions.h" |
| #include "ui/gfx/skia_util.h" |
| @@ -80,6 +81,7 @@ using WebKit::WebGestureEvent; |
| using WebKit::WebInputEvent; |
| using WebKit::WebKeyboardEvent; |
| using WebKit::WebMouseEvent; |
| +using WebKit::WebMouseWheelEvent; |
| using WebKit::WebNavigationPolicy; |
| using WebKit::WebPagePopup; |
| using WebKit::WebPoint; |
| @@ -187,6 +189,178 @@ ui::TextInputMode ConvertInputMode( |
| namespace content { |
| +// RenderWidget::ScreenMetricsEmulator ---------------------------------------- |
| + |
| +class RenderWidget::ScreenMetricsEmulator { |
| + public: |
| + ScreenMetricsEmulator( |
| + RenderWidget* widget, |
| + const gfx::Size& device_size, |
| + const gfx::Rect& widget_rect, |
| + float device_scale_factor, |
| + bool fit_to_view); |
| + virtual ~ScreenMetricsEmulator(); |
| + |
| + float scale() { return scale_; } |
| + gfx::Rect widget_rect() const { return widget_rect_; } |
| + gfx::Rect original_screen_rect() const { return original_view_screen_rect_; } |
| + |
| + void ChangeEmulationParams( |
| + const gfx::Size& device_size, |
| + const gfx::Rect& widget_rect, |
| + float device_scale_factor, |
| + bool fit_to_view); |
| + |
| + // The following methods alter handlers' behavior for messages related to |
| + // widget size and position. |
| + void OnResizeMessage(const ViewMsg_Resize_Params& params); |
| + void OnUpdateScreenRectsMessage(const gfx::Rect view_screen_rect, |
|
aelias_OOO_until_Jul13
2013/09/27 22:51:14
Either add & or remove the "const".
dgozman
2013/10/01 06:22:16
Done.
|
| + const gfx::Rect window_screen_rect); |
| + void OnShowContextMenu(ContextMenuParams* params); |
| + |
| + private: |
| + void Apply(float overdraw_bottom_height, |
| + gfx::Rect resizer_rect, bool is_fullscreen); |
| + |
| + RenderWidget* widget_; |
| + |
| + // Parameters as passed by RenderWidget::EmulateScreenMetrics. |
| + gfx::Size device_size_; |
| + gfx::Rect widget_rect_; |
| + float device_scale_factor_; |
| + bool fit_to_view_; |
| + |
| + // The computed scaled used to fit widget into browser window. |
| + float scale_; |
| + |
| + // Original values to restore back after emulation ends. |
| + gfx::Size original_size_; |
| + gfx::Size original_physical_backing_size_; |
| + WebKit::WebScreenInfo original_screen_info_; |
| + gfx::Rect original_view_screen_rect_; |
| + gfx::Rect original_window_screen_rect_; |
| +}; |
| + |
| +RenderWidget::ScreenMetricsEmulator::ScreenMetricsEmulator( |
| + RenderWidget* widget, |
| + const gfx::Size& device_size, |
| + const gfx::Rect& widget_rect, |
| + float device_scale_factor, |
| + bool fit_to_view) |
| + : widget_(widget), |
| + device_size_(device_size), |
| + widget_rect_(widget_rect), |
| + device_scale_factor_(device_scale_factor), |
| + fit_to_view_(fit_to_view), |
| + scale_(1.f) { |
| + original_size_ = widget_->size_; |
| + original_physical_backing_size_ = widget_->physical_backing_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_->overdraw_bottom_height_, |
| + widget_->resizer_rect_, widget_->is_fullscreen_); |
| +} |
| + |
| +RenderWidget::ScreenMetricsEmulator::~ScreenMetricsEmulator() { |
| + widget_->screen_info_ = original_screen_info_; |
| + |
| + widget_->Send(new ViewHostMsg_SetExpectedSize(widget_->routing_id(), |
| + gfx::Size())); |
| + |
| + widget_->SetDeviceScaleFactor(original_screen_info_.deviceScaleFactor); |
| + widget_->SetScreenMetricsEmulationParameters(false /* enabled */, 1.f, 1.f); |
| + 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_->overdraw_bottom_height_, widget_->resizer_rect_, |
| + widget_->is_fullscreen_, NO_RESIZE_ACK); |
| +} |
| + |
| +void RenderWidget::ScreenMetricsEmulator::ChangeEmulationParams( |
| + const gfx::Size& device_size, |
| + const gfx::Rect& widget_rect, |
| + float device_scale_factor, |
| + bool fit_to_view) { |
| + device_size_ = device_size; |
| + widget_rect_ = widget_rect; |
| + device_scale_factor_ = device_scale_factor; |
| + fit_to_view_ = fit_to_view; |
| + Apply(widget_->overdraw_bottom_height_, |
| + widget_->resizer_rect_, widget_->is_fullscreen_); |
| +} |
| + |
| +void RenderWidget::ScreenMetricsEmulator::Apply( |
| + float overdraw_bottom_height, gfx::Rect resizer_rect, bool is_fullscreen) { |
| + if (fit_to_view_) { |
| + float width_ratio = !original_size_.width() ? 1.f : |
|
aelias_OOO_until_Jul13
2013/09/27 22:51:14
Setting a default value when a divide-by-zero woul
dgozman
2013/10/01 06:22:16
Added DCHECK.
|
| + static_cast<float>(widget_rect_.width()) / original_size_.width(); |
| + float height_ratio = !original_size_.height() ? 1.f : |
| + static_cast<float>(widget_rect_.height()) / original_size_.height(); |
| + float ratio = std::max(1.0f, std::max(width_ratio, height_ratio)); |
| + scale_ = 1.f / ratio; |
|
aelias_OOO_until_Jul13
2013/09/27 22:51:14
widget_rect_ being zero would also cause a divide-
dgozman
2013/10/01 06:22:16
Ratio is at least 1.f (see line above).
|
| + } else { |
| + scale_ = 1.f; |
| + } |
| + |
| + widget_->screen_info_.rect = gfx::Rect(device_size_); |
| + widget_->screen_info_.availableRect = gfx::Rect(device_size_); |
| + widget_->screen_info_.deviceScaleFactor = device_scale_factor_; |
| + |
| + // Pass two 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 scaling transform to the |
| + // root layer. |
| + widget_->SetScreenMetricsEmulationParameters(true /* enabled */, |
| + original_screen_info_.deviceScaleFactor, scale_); |
| + |
| + widget_->SetDeviceScaleFactor(device_scale_factor_); |
| + widget_->view_screen_rect_ = widget_rect_; |
| + widget_->window_screen_rect_ = widget_->screen_info_.availableRect; |
| + |
| + // Make host accept an image of different size. |
| + widget_->Send(new ViewHostMsg_SetExpectedSize(widget_->routing_id(), |
| + gfx::ToCeiledSize(gfx::ScaleSize(widget_rect_.size(), scale_)))); |
| + |
| + gfx::Size physical_backing_size = gfx::ToCeiledSize(gfx::ScaleSize( |
| + widget_rect_.size(), original_screen_info_.deviceScaleFactor * scale_)); |
| + widget_->Resize(widget_rect_.size(), physical_backing_size, |
| + overdraw_bottom_height, resizer_rect, is_fullscreen, NO_RESIZE_ACK); |
| +} |
| + |
| +void RenderWidget::ScreenMetricsEmulator::OnResizeMessage( |
| + const ViewMsg_Resize_Params& params) { |
| + bool need_ack = params.new_size != original_size_; |
| + original_size_ = params.new_size; |
| + original_physical_backing_size_ = params.physical_backing_size; |
| + original_screen_info_ = params.screen_info; |
| + Apply(params.overdraw_bottom_height, params.resizer_rect, |
| + params.is_fullscreen); |
| + |
| + 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; |
| + widget_->Send(new ViewHostMsg_UpdateScreenRects_ACK(widget_->routing_id())); |
| +} |
| + |
| +void RenderWidget::ScreenMetricsEmulator::OnShowContextMenu( |
| + ContextMenuParams* params) { |
| + params->x *= scale_; |
| + params->y *= scale_; |
| +} |
| + |
| +// RenderWidget --------------------------------------------------------------- |
| + |
| RenderWidget::RenderWidget(WebKit::WebPopupType popup_type, |
| const WebKit::WebScreenInfo& screen_info, |
| bool swapped_out, |
| @@ -232,6 +406,7 @@ RenderWidget::RenderWidget(WebKit::WebPopupType popup_type, |
| #if defined(OS_ANDROID) |
| outstanding_ime_acks_(0), |
| #endif |
| + popup_origin_scale_for_emulation_(0.f), |
| weak_ptr_factory_(this) { |
| if (!swapped_out) |
| RenderProcess::current()->AddRefProcess(); |
| @@ -370,6 +545,49 @@ bool RenderWidget::UsingSynchronousRendererCompositor() const { |
| #endif |
| } |
| +void RenderWidget::EmulateScreenMetrics( |
| + bool enabled, |
| + const gfx::Size& device_size, |
| + const gfx::Rect& widget_rect, |
| + float device_scale_factor, |
| + bool fit_to_view) { |
| + if (enabled) { |
| + if (!screen_metrics_emulator_) { |
| + screen_metrics_emulator_.reset(new ScreenMetricsEmulator(this, |
| + device_size, widget_rect, device_scale_factor, fit_to_view)); |
| + } else { |
| + screen_metrics_emulator_->ChangeEmulationParams(device_size, |
| + widget_rect, device_scale_factor, fit_to_view); |
| + } |
| + } else { |
| + screen_metrics_emulator_.reset(); |
| + } |
| +} |
| + |
| +void RenderWidget::SetPopupOriginAdjustmentsForEmulation( |
| + ScreenMetricsEmulator* emulator) { |
| + popup_origin_scale_for_emulation_ = emulator->scale(); |
| + popup_view_origin_for_emulation_ = emulator->widget_rect().origin(); |
| + popup_screen_origin_for_emulation_ = |
| + emulator->original_screen_rect().origin(); |
| +} |
| + |
| +void RenderWidget::SetScreenMetricsEmulationParameters( |
| + bool enabled, float device_scale_factor, float root_layer_scale) { |
| + // This is only supported in RenderView. |
| + NOTREACHED(); |
| +} |
| + |
| +void RenderWidget::SetExternalPopupOriginAdjustmentsForEmulation( |
| + ExternalPopupMenu* popup, ScreenMetricsEmulator* emulator) { |
| + popup->SetOriginScaleForEmulation(emulator->scale()); |
| +} |
| + |
| +void RenderWidget::OnShowHostContextMenu(ContextMenuParams* params) { |
| + if (screen_metrics_emulator_) |
| + screen_metrics_emulator_->OnShowContextMenu(params); |
| +} |
| + |
| bool RenderWidget::OnMessageReceived(const IPC::Message& message) { |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(RenderWidget, message) |
| @@ -533,6 +751,11 @@ void RenderWidget::OnCreatingNewAck() { |
| } |
| void RenderWidget::OnResize(const ViewMsg_Resize_Params& params) { |
| + if (screen_metrics_emulator_) { |
| + screen_metrics_emulator_->OnResizeMessage(params); |
| + return; |
| + } |
| + |
| screen_info_ = params.screen_info; |
| SetDeviceScaleFactor(screen_info_.deviceScaleFactor); |
| Resize(params.new_size, params.physical_backing_size, |
| @@ -823,6 +1046,7 @@ void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event, |
| const ui::LatencyInfo& latency_info, |
| bool is_keyboard_shortcut) { |
| handling_input_event_ = true; |
| + |
| if (!input_event) { |
| handling_input_event_ = false; |
| return; |
| @@ -1792,7 +2016,16 @@ void RenderWidget::setToolTipText(const WebKit::WebString& text, |
| Send(new ViewHostMsg_SetTooltipText(routing_id_, text, hint)); |
| } |
| -void RenderWidget::setWindowRect(const WebRect& pos) { |
| +void RenderWidget::setWindowRect(const WebRect& rect) { |
| + WebRect pos = rect; |
| + if (popup_origin_scale_for_emulation_) { |
| + float scale = popup_origin_scale_for_emulation_; |
| + pos.x = popup_screen_origin_for_emulation_.x() + |
| + (pos.x - popup_view_origin_for_emulation_.x()) * scale; |
| + pos.y = popup_screen_origin_for_emulation_.y() + |
| + (pos.y - popup_view_origin_for_emulation_.y()) * scale; |
| + } |
| + |
| if (did_show_) { |
| if (!RenderThreadImpl::current()->layout_test_mode()) { |
| Send(new ViewHostMsg_RequestMove(routing_id_, pos)); |
| @@ -2033,6 +2266,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_->OnUpdateScreenRectsMessage( |
| + view_screen_rect, window_screen_rect); |
| + return; |
| + } |
| view_screen_rect_ = view_screen_rect; |
| window_screen_rect_ = window_screen_rect; |
| Send(new ViewHostMsg_UpdateScreenRects_ACK(routing_id())); |