diff options
Diffstat (limited to 'content/renderer')
-rw-r--r-- | content/renderer/devtools/devtools_agent.cc | 17 | ||||
-rw-r--r-- | content/renderer/devtools/devtools_agent.h | 5 | ||||
-rw-r--r-- | content/renderer/external_popup_menu.cc | 15 | ||||
-rw-r--r-- | content/renderer/external_popup_menu.h | 7 | ||||
-rw-r--r-- | content/renderer/render_view_impl.cc | 17 | ||||
-rw-r--r-- | content/renderer/render_view_impl.h | 2 | ||||
-rw-r--r-- | content/renderer/render_widget.cc | 238 | ||||
-rw-r--r-- | content/renderer/render_widget.h | 31 | ||||
-rw-r--r-- | content/renderer/web_preferences.cc | 1 |
9 files changed, 327 insertions, 6 deletions
diff --git a/content/renderer/devtools/devtools_agent.cc b/content/renderer/devtools/devtools_agent.cc index 635acc1..cb9aeba 100644 --- a/content/renderer/devtools/devtools_agent.cc +++ b/content/renderer/devtools/devtools_agent.cc @@ -22,6 +22,7 @@ #include "third_party/WebKit/public/web/WebConsoleMessage.h" #include "third_party/WebKit/public/web/WebDevToolsAgent.h" #include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebSettings.h" #include "third_party/WebKit/public/web/WebView.h" #if defined(USE_TCMALLOC) @@ -144,6 +145,22 @@ void DevToolsAgent::setTraceEventCallback(TraceEventCallback cb) { } } +void DevToolsAgent::enableDeviceEmulation( + const WebKit::WebSize& device_size, + const WebKit::WebRect& view_rect, + float device_scale_factor, + bool fit_to_view) { + RenderViewImpl* impl = static_cast<RenderViewImpl*>(render_view()); + impl->webview()->settings()->setForceCompositingMode(true); + impl->EnableScreenMetricsEmulation(gfx::Size(device_size), + gfx::Rect(view_rect), device_scale_factor, fit_to_view); +} + +void DevToolsAgent::disableDeviceEmulation() { + RenderViewImpl* impl = static_cast<RenderViewImpl*>(render_view()); + impl->DisableScreenMetricsEmulation(); +} + #if defined(USE_TCMALLOC) && !defined(OS_WIN) static void AllocationVisitor(void* data, const void* ptr) { typedef WebKit::WebDevToolsAgentClient::AllocatedObjectVisitor Visitor; diff --git a/content/renderer/devtools/devtools_agent.h b/content/renderer/devtools/devtools_agent.h index 4ac22db..9860ed7 100644 --- a/content/renderer/devtools/devtools_agent.h +++ b/content/renderer/devtools/devtools_agent.h @@ -53,6 +53,11 @@ class DevToolsAgent : public RenderViewObserver, virtual void clearBrowserCookies(); virtual void visitAllocatedObjects(AllocatedObjectVisitor* visitor); virtual void setTraceEventCallback(TraceEventCallback cb); + virtual void enableDeviceEmulation( + const WebKit::WebSize& device_size, + const WebKit::WebRect& view_rect, float device_scale_factor, + bool fit_to_view); + virtual void disableDeviceEmulation(); void OnAttach(); void OnReattach(const std::string& agent_state); diff --git a/content/renderer/external_popup_menu.cc b/content/renderer/external_popup_menu.cc index 08d71e9..070ccd3 100644 --- a/content/renderer/external_popup_menu.cc +++ b/content/renderer/external_popup_menu.cc @@ -18,12 +18,23 @@ ExternalPopupMenu::ExternalPopupMenu( WebKit::WebExternalPopupMenuClient* popup_menu_client) : render_view_(render_view), popup_menu_info_(popup_menu_info), - popup_menu_client_(popup_menu_client) { + popup_menu_client_(popup_menu_client), + origin_scale_for_emulation_(0) { +} + +void ExternalPopupMenu::SetOriginScaleForEmulation(float scale) { + origin_scale_for_emulation_ = scale; } void ExternalPopupMenu::show(const WebKit::WebRect& bounds) { + WebKit::WebRect rect = bounds; + if (origin_scale_for_emulation_) { + rect.x *= origin_scale_for_emulation_; + rect.y *= origin_scale_for_emulation_; + } + ViewHostMsg_ShowPopup_Params popup_params; - popup_params.bounds = bounds; + popup_params.bounds = rect; popup_params.item_height = popup_menu_info_.itemHeight; popup_params.item_font_size = popup_menu_info_.itemFontSize; popup_params.selected_item = popup_menu_info_.selectedIndex; diff --git a/content/renderer/external_popup_menu.h b/content/renderer/external_popup_menu.h index 729205f..28d65ac 100644 --- a/content/renderer/external_popup_menu.h +++ b/content/renderer/external_popup_menu.h @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "third_party/WebKit/public/web/WebExternalPopupMenu.h" #include "third_party/WebKit/public/web/WebPopupMenuInfo.h" +#include "ui/gfx/point.h" namespace WebKit { class WebExternalPopupMenuClient; @@ -26,6 +27,8 @@ class ExternalPopupMenu : public WebKit::WebExternalPopupMenu { virtual ~ExternalPopupMenu() {} + void SetOriginScaleForEmulation(float scale); + #if defined(OS_MACOSX) // Called when the user has selected an item. |selected_item| is -1 if the // user canceled the popup. @@ -46,6 +49,10 @@ class ExternalPopupMenu : public WebKit::WebExternalPopupMenu { WebKit::WebPopupMenuInfo popup_menu_info_; WebKit::WebExternalPopupMenuClient* popup_menu_client_; + // Popups may be displaced when screen metrics emulation is enabled. + // This scale is used to properly adjust popup position. + float origin_scale_for_emulation_; + DISALLOW_COPY_AND_ASSIGN(ExternalPopupMenu); }; diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 6f4f908..963e30e 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -2339,6 +2339,10 @@ WebView* RenderViewImpl::createView( WebWidget* RenderViewImpl::createPopupMenu(WebKit::WebPopupType popup_type) { RenderWidget* widget = RenderWidget::Create(routing_id_, popup_type, screen_info_); + if (screen_metrics_emulator_) { + widget->SetPopupOriginAdjustmentsForEmulation( + screen_metrics_emulator_.get()); + } return widget->webwidget(); } @@ -2355,6 +2359,10 @@ WebExternalPopupMenu* RenderViewImpl::createExternalPopupMenu( return NULL; external_popup_menu_.reset( new ExternalPopupMenu(this, popup_menu_info, popup_menu_client)); + if (screen_metrics_emulator_) { + SetExternalPopupOriginAdjustmentsForEmulation( + external_popup_menu_.get(), screen_metrics_emulator_.get()); + } return external_popup_menu_.get(); } @@ -2633,6 +2641,7 @@ void RenderViewImpl::showContextMenu( params.x = touch_editing_context_menu_location_.x(); params.y = touch_editing_context_menu_location_.y(); } + OnShowHostContextMenu(¶ms); // Plugins, e.g. PDF, don't currently update the render view when their // selected text changes, but the context menu params do contain the updated @@ -6084,6 +6093,14 @@ bool RenderViewImpl::AllowPartialSwap() const { return allow_partial_swap_; } +void RenderViewImpl::SetScreenMetricsEmulationParameters( + float device_scale_factor, float root_layer_scale) { + if (webview()) { + webview()->setCompositorDeviceScaleFactorOverride(device_scale_factor); + webview()->setRootLayerScaleTransform(root_layer_scale); + } +} + bool RenderViewImpl::ScheduleFileChooser( const FileChooserParams& params, WebFileChooserCompletion* completion) { diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index b7220ea..1dc7e85 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h @@ -774,6 +774,8 @@ class CONTENT_EXPORT RenderViewImpl explicit RenderViewImpl(RenderViewImplParams* params); void Initialize(RenderViewImplParams* params); + virtual void SetScreenMetricsEmulationParameters( + float device_scale_factor, float root_layer_scale) OVERRIDE; // Do not delete directly. This class is reference counted. virtual ~RenderViewImpl(); diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index abb144d..3c64e51 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())); } diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index 0d606f8..dbab733 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h @@ -65,9 +65,11 @@ class Range; } namespace content { +class ExternalPopupMenu; class PepperPluginInstanceImpl; class RenderWidgetCompositor; class RenderWidgetTest; +struct ContextMenuParams; struct GpuRenderingStats; struct WebPluginGeometry; @@ -223,6 +225,22 @@ class CONTENT_EXPORT RenderWidget bool is_swapped_out() { return is_swapped_out_; } + // ScreenMetricsEmulator class manages screen emulation inside a render + // widget. This includes resizing, placing view on the screen at desired + // position, changing device scale factor, and scaling down the whole + // widget if required to fit into the browser window. + class ScreenMetricsEmulator; + + // Emulates screen and widget metrics. Supplied values override everything + // coming from host. + void EnableScreenMetricsEmulation( + const gfx::Size& device_size, + const gfx::Rect& widget_rect, + float device_scale_factor, + bool fit_to_view); + void DisableScreenMetricsEmulation(); + void SetPopupOriginAdjustmentsForEmulation(ScreenMetricsEmulator* emulator); + protected: // Friend RefCounted so that the dtor can be non-public. Using this class // without ref-counting is an error. @@ -291,6 +309,11 @@ class CONTENT_EXPORT RenderWidget const gfx::Rect& resizer_rect, bool is_fullscreen, ResizeAck resize_ack); + virtual void SetScreenMetricsEmulationParameters( + float device_scale_factor, float root_layer_scale); + void SetExternalPopupOriginAdjustmentsForEmulation( + ExternalPopupMenu* popup, ScreenMetricsEmulator* emulator); + virtual void OnShowHostContextMenu(ContextMenuParams* params); // RenderWidget IPC message handlers void OnHandleInputEvent(const WebKit::WebInputEvent* event, @@ -752,6 +775,14 @@ class CONTENT_EXPORT RenderWidget int outstanding_ime_acks_; #endif + scoped_ptr<ScreenMetricsEmulator> screen_metrics_emulator_; + + // Popups may be displaced when screen metrics emulation is enabled. + // These values are used to properly adjust popup position. + gfx::Point popup_view_origin_for_emulation_; + gfx::Point popup_screen_origin_for_emulation_; + float popup_origin_scale_for_emulation_; + base::WeakPtrFactory<RenderWidget> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(RenderWidget); diff --git a/content/renderer/web_preferences.cc b/content/renderer/web_preferences.cc index a7df752..f558189 100644 --- a/content/renderer/web_preferences.cc +++ b/content/renderer/web_preferences.cc @@ -348,6 +348,7 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) { prefs.viewport_meta_zero_values_quirk); settings->setIgnoreMainFrameOverflowHiddenQuirk( prefs.ignore_main_frame_overflow_hidden_quirk); + settings->setMainFrameClipsContent(false); #endif WebNetworkStateNotifier::setOnLine(prefs.is_online); |