Index: content/renderer/render_widget.cc |
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc |
index abb144d592fe57e85ec293e64de9776f7a6456b7..3c64e512b0e169d9881575354f1c011328f5836a 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,172 @@ 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, |
+ 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_->SetDeviceScaleFactor(original_screen_info_.deviceScaleFactor); |
+ widget_->SetScreenMetricsEmulationParameters(0.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_) { |
+ DCHECK(!original_size_.IsEmpty()); |
+ float width_ratio = |
+ static_cast<float>(widget_rect_.width()) / original_size_.width(); |
+ float height_ratio = |
+ 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; |
+ } 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( |
+ original_screen_info_.deviceScaleFactor, scale_); |
+ |
+ widget_->SetDeviceScaleFactor(device_scale_factor_); |
+ widget_->view_screen_rect_ = widget_rect_; |
+ widget_->window_screen_rect_ = widget_->screen_info_.availableRect; |
+ |
+ gfx::Size physical_backing_size = gfx::ToCeiledSize(gfx::ScaleSize( |
+ original_size_, original_screen_info_.deviceScaleFactor)); |
+ 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_ && |
+ !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; |
+ 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; |
+} |
+ |
+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 +400,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 +539,48 @@ bool RenderWidget::UsingSynchronousRendererCompositor() const { |
#endif |
} |
+void RenderWidget::EnableScreenMetricsEmulation( |
+ const gfx::Size& device_size, |
+ const gfx::Rect& widget_rect, |
+ float device_scale_factor, |
+ bool fit_to_view) { |
+ 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); |
+ } |
+} |
+ |
+void RenderWidget::DisableScreenMetricsEmulation() { |
+ 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( |
+ 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) |
@@ -532,6 +743,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, |
@@ -1791,7 +2007,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)); |
@@ -2032,8 +2257,13 @@ void RenderWidget::OnSetTextDirection(WebTextDirection direction) { |
void RenderWidget::OnUpdateScreenRects(const gfx::Rect& view_screen_rect, |
const gfx::Rect& window_screen_rect) { |
- view_screen_rect_ = view_screen_rect; |
- window_screen_rect_ = window_screen_rect; |
+ if (screen_metrics_emulator_) { |
+ screen_metrics_emulator_->OnUpdateScreenRectsMessage( |
+ view_screen_rect, window_screen_rect); |
+ } else { |
+ view_screen_rect_ = view_screen_rect; |
+ window_screen_rect_ = window_screen_rect; |
+ } |
Send(new ViewHostMsg_UpdateScreenRects_ACK(routing_id())); |
} |