| Index: content/renderer/render_widget.cc
|
| ===================================================================
|
| --- content/renderer/render_widget.cc (revision 221161)
|
| +++ content/renderer/render_widget.cc (working copy)
|
| @@ -53,10 +53,11 @@
|
| #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"
|
| +#include "ui/gfx/vector2d_conversions.h"
|
| #include "ui/gl/gl_switches.h"
|
| #include "ui/surface/transport_dib.h"
|
| #include "webkit/renderer/compositor_bindings/web_rendering_stats_impl.h"
|
| @@ -79,6 +80,7 @@
|
| using WebKit::WebInputEvent;
|
| using WebKit::WebKeyboardEvent;
|
| using WebKit::WebMouseEvent;
|
| +using WebKit::WebMouseWheelEvent;
|
| using WebKit::WebNavigationPolicy;
|
| using WebKit::WebPagePopup;
|
| using WebKit::WebPoint;
|
| @@ -386,6 +388,7 @@
|
| IPC_MESSAGE_HANDLER(ViewMsg_UpdateRect_ACK, OnUpdateRectAck)
|
| IPC_MESSAGE_HANDLER(ViewMsg_SwapBuffers_ACK,
|
| OnViewContextSwapBuffersComplete)
|
| + IPC_MESSAGE_HANDLER(ViewMsg_EmulateDevice_ACK, OnEmulateDeviceAck)
|
| IPC_MESSAGE_HANDLER(ViewMsg_SetInputMethodActive, OnSetInputMethodActive)
|
| IPC_MESSAGE_HANDLER(ViewMsg_ImeSetComposition, OnImeSetComposition)
|
| IPC_MESSAGE_HANDLER(ViewMsg_ImeConfirmComposition, OnImeConfirmComposition)
|
| @@ -522,6 +525,53 @@
|
| Release();
|
| }
|
|
|
| +void RenderWidget::EmulateDevice(
|
| + bool enabled,
|
| + const gfx::Size& device_size,
|
| + const gfx::Rect& widget_rect,
|
| + float device_scale_factor,
|
| + bool fit_to_view) {
|
| + pending_device_emulation_enabled_ = enabled;
|
| + if (enabled) {
|
| + pending_device_emulation_helper_.reset(new DeviceEmulationHelper(
|
| + device_size,
|
| + widget_rect,
|
| + device_scale_factor,
|
| + fit_to_view));
|
| + } else {
|
| + pending_device_emulation_helper_.reset();
|
| + }
|
| + Send(new ViewHostMsg_EmulateDevice(routing_id_, enabled));
|
| +}
|
| +
|
| +void RenderWidget::OnEmulateDeviceAck(bool enabled) {
|
| + // We may have got another emulate device request while sending message
|
| + // to the host. If the host idea of whether device emulation is enabled
|
| + // differs, wait for another ack with the right |enabled| value.
|
| + if (enabled != pending_device_emulation_enabled_)
|
| + return;
|
| +
|
| + if (pending_device_emulation_enabled_) {
|
| + if (!device_emulation_helper_) {
|
| + device_emulation_helper_ = pending_device_emulation_helper_.Pass();
|
| + device_emulation_helper_->BeginEmulation(this);
|
| + } else {
|
| + device_emulation_helper_->ChangeEmulationParams(
|
| + this, pending_device_emulation_helper_.get());
|
| + pending_device_emulation_helper_.reset();
|
| + }
|
| + } else {
|
| + if (device_emulation_helper_)
|
| + device_emulation_helper_->EndEmulation(this);
|
| + device_emulation_helper_.reset();
|
| + }
|
| +}
|
| +
|
| +void RenderWidget::SetDeviceEmulationScale(float scale) {
|
| + // This is only supported in RenderView.
|
| + NOTREACHED();
|
| +}
|
| +
|
| // Got a response from the browser after the renderer decided to create a new
|
| // view.
|
| void RenderWidget::OnCreatingNewAck() {
|
| @@ -531,6 +581,11 @@
|
| }
|
|
|
| void RenderWidget::OnResize(const ViewMsg_Resize_Params& params) {
|
| + if (device_emulation_helper_) {
|
| + device_emulation_helper_->OnResizeMessage(this, params);
|
| + return;
|
| + }
|
| +
|
| screen_info_ = params.screen_info;
|
| SetDeviceScaleFactor(screen_info_.deviceScaleFactor);
|
| Resize(params.new_size, params.physical_backing_size,
|
| @@ -813,6 +868,21 @@
|
| const ui::LatencyInfo& latency_info,
|
| bool is_keyboard_shortcut) {
|
| handling_input_event_ = true;
|
| +
|
| + scoped_ptr<const WebKit::WebInputEvent> owner;
|
| + if (device_emulation_helper_) {
|
| + input_event = device_emulation_helper_->ConvertInputEventToEmulated(
|
| + this, input_event);
|
| + if (input_event)
|
| + owner.reset(input_event);
|
| + }
|
| + if (popup_device_emulation_helper_) {
|
| +// input_event = popup_device_emulation_helper_->ConvertInputEventToEmulated(
|
| +// this, input_event);
|
| +// if (input_event)
|
| +// owner.reset(input_event);
|
| + }
|
| +
|
| if (!input_event) {
|
| handling_input_event_ = false;
|
| return;
|
| @@ -1425,6 +1495,8 @@
|
| // The invalidated rect might be outside the bounds of the view.
|
| gfx::Rect view_rect(size_);
|
| gfx::Rect damaged_rect = gfx::IntersectRects(view_rect, rect);
|
| + if (popup_device_emulation_helper_)
|
| + damaged_rect = view_rect;
|
| if (damaged_rect.IsEmpty())
|
| return;
|
|
|
| @@ -1776,7 +1848,13 @@
|
| 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_device_emulation_helper_) {
|
| + pos = popup_device_emulation_helper_->ConvertPopupScreenRectFromEmulated(
|
| + this, rect);
|
| + }
|
| +
|
| if (did_show_) {
|
| if (!RenderThreadImpl::current()->layout_test_mode()) {
|
| Send(new ViewHostMsg_RequestMove(routing_id_, pos));
|
| @@ -2017,6 +2095,11 @@
|
|
|
| void RenderWidget::OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
|
| const gfx::Rect& window_screen_rect) {
|
| + if (device_emulation_helper_) {
|
| + device_emulation_helper_->OnUpdateScreenRectsMessage(
|
| + this, 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()));
|
| @@ -2531,4 +2614,269 @@
|
| return context.Pass();
|
| }
|
|
|
| +// This class scales input event's coordinates, and then sets screen coordinates
|
| +// to emulate specific view position on the screen.
|
| +class DeviceEmulationEventRewriter : public InputEventRewriter {
|
| + public:
|
| + DeviceEmulationEventRewriter() {}
|
| + virtual ~DeviceEmulationEventRewriter() {}
|
| +
|
| + void SetParams(float scale, const gfx::Point& origin);
|
| +
|
| + // InputEventRewriter implementation.
|
| + virtual WebKit::WebInputEvent* RewriteInputEvent(
|
| + const WebKit::WebInputEvent* event);
|
| +
|
| + private:
|
| + void ConvertMouseEventToEmulated(WebKit::WebMouseEvent* event);
|
| + void ConvertTouchPointToEmulated(WebKit::WebTouchPoint* point);
|
| +
|
| + // Event coordinates are scaled by this value.
|
| + float scale_;
|
| +
|
| + // Widget screen position, used to set proper event screen coordinates.
|
| + gfx::Point origin_;
|
| +};
|
| +
|
| +void DeviceEmulationEventRewriter::SetParams(
|
| + float scale, const gfx::Point& origin) {
|
| + scale_ = scale;
|
| + origin_ = origin;
|
| +}
|
| +
|
| +WebKit::WebInputEvent* DeviceEmulationEventRewriter::RewriteInputEvent(
|
| + const WebKit::WebInputEvent* event) {
|
| + if (!event)
|
| + return NULL;
|
| +
|
| + if (WebInputEvent::isKeyboardEventType(event->type)) {
|
| + const WebKeyboardEvent& keyboard_event =
|
| + *static_cast<const WebKeyboardEvent*>(event);
|
| + WebKeyboardEvent* result = new WebKeyboardEvent(keyboard_event);
|
| + return result;
|
| + }
|
| +
|
| + if (WebInputEvent::isMouseEventType(event->type)) {
|
| + const WebMouseEvent& mouse_event =
|
| + *static_cast<const WebMouseEvent*>(event);
|
| + WebMouseEvent* result = new WebMouseEvent(mouse_event);
|
| + ConvertMouseEventToEmulated(result);
|
| + return result;
|
| + }
|
| +
|
| + if (WebInputEvent::MouseWheel == event->type) {
|
| + const WebMouseWheelEvent& mouse_wheel_event =
|
| + *static_cast<const WebMouseWheelEvent*>(event);
|
| + WebMouseWheelEvent* result = new WebMouseWheelEvent(mouse_wheel_event);
|
| + ConvertMouseEventToEmulated(result);
|
| + return result;
|
| + }
|
| +
|
| + if (WebInputEvent::isGestureEventType(event->type)) {
|
| + const WebGestureEvent& gesture_event =
|
| + *static_cast<const WebGestureEvent*>(event);
|
| + WebGestureEvent* result = new WebGestureEvent(gesture_event);
|
| + result->x = 1.f / scale_ * result->x;
|
| + result->y = 1.f / scale_ * result->y;
|
| + result->globalX = origin_.x() + result->x;
|
| + result->globalY = origin_.y() + result->y;
|
| + return result;
|
| + }
|
| +
|
| + if (WebInputEvent::isTouchEventType(event->type)) {
|
| + const WebTouchEvent& touch_event =
|
| + *static_cast<const WebTouchEvent*>(event);
|
| + WebTouchEvent* result = new WebTouchEvent(touch_event);
|
| + for (size_t index = 0; index < result->touchesLength; ++index) {
|
| + ConvertTouchPointToEmulated(&result->touches[index]);
|
| + }
|
| + for (size_t index = 0; index < result->changedTouchesLength; ++index) {
|
| + ConvertTouchPointToEmulated(&result->changedTouches[index]);
|
| + }
|
| + for (size_t index = 0; index < result->targetTouchesLength; ++index) {
|
| + ConvertTouchPointToEmulated(&result->targetTouches[index]);
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + return NULL;
|
| +}
|
| +
|
| +void DeviceEmulationEventRewriter::ConvertMouseEventToEmulated(
|
| + WebKit::WebMouseEvent* event) {
|
| + event->x = 1.f / scale_ * event->x;
|
| + event->y = 1.f / scale_ * event->y;
|
| + event->movementX = 1.f / scale_ * event->movementX;
|
| + event->movementY = 1.f / scale_ * event->movementY;
|
| + event->windowX = origin_.x() + event->x;
|
| + event->windowY = origin_.y() + event->y;
|
| + event->globalX = event->windowX;
|
| + event->globalY = event->windowY;
|
| +}
|
| +
|
| +void DeviceEmulationEventRewriter::ConvertTouchPointToEmulated(
|
| + WebKit::WebTouchPoint* point) {
|
| + point->position.x = 1.f / scale_ * point->position.x;
|
| + point->position.y = 1.f / scale_ * point->position.y;
|
| + point->screenPosition.x = origin_.x() + point->position.x;
|
| + point->screenPosition.y = origin_.y() + point->position.y;
|
| +}
|
| +
|
| +
|
| +RenderWidget::DeviceEmulationHelper::DeviceEmulationHelper(
|
| + 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),
|
| + weak_ptr_factory_(this) {
|
| +}
|
| +
|
| +RenderWidget::DeviceEmulationHelper::~DeviceEmulationHelper() {
|
| +}
|
| +
|
| +void RenderWidget::DeviceEmulationHelper::BeginEmulation(RenderWidget* widget) {
|
| + 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_;
|
| + input_event_rewriter_.reset(new DeviceEmulationEventRewriter);
|
| + Apply(widget, widget->overdraw_bottom_height_, widget->resizer_rect_,
|
| + widget->is_fullscreen_);
|
| +}
|
| +
|
| +void RenderWidget::DeviceEmulationHelper::ChangeEmulationParams(
|
| + RenderWidget* widget, DeviceEmulationHelper* params) {
|
| + device_size_ = params->device_size_;
|
| + widget_rect_ = params->widget_rect_;
|
| + device_scale_factor_ = params->device_scale_factor_;
|
| + fit_to_view_ = params->fit_to_view_;
|
| + Apply(widget, widget->overdraw_bottom_height_, widget->resizer_rect_,
|
| + widget->is_fullscreen_);
|
| +}
|
| +
|
| +void RenderWidget::DeviceEmulationHelper::EndEmulation(RenderWidget* widget) {
|
| + widget->screen_info_ = original_screen_info_;
|
| + if (widget->compositor_) {
|
| + // Passing zero cancels the override.
|
| + widget->compositor_->OverrideDeviceScaleFactor(0.f);
|
| + }
|
| + widget->SetDeviceScaleFactor(original_screen_info_.deviceScaleFactor);
|
| + widget->SetDeviceEmulationScale(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::DeviceEmulationHelper::Apply(RenderWidget* widget,
|
| + float overdraw_bottom_height, gfx::Rect resizer_rect, bool is_fullscreen) {
|
| + if (fit_to_view_) {
|
| + float width_ratio = !original_size_.width() ? 1.f :
|
| + 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;
|
| + } else {
|
| + scale_ = 1.f;
|
| + }
|
| +
|
| + input_event_rewriter_->SetParams(scale_, widget_rect_.origin());
|
| + InputHandlerManager* input_handler_manager =
|
| + RenderThreadImpl::current()->input_handler_manager();
|
| + if (input_handler_manager) {
|
| + // Make a copy to be owned by InputHandlerManager.
|
| + scoped_ptr<DeviceEmulationEventRewriter> copy(
|
| + new DeviceEmulationEventRewriter(*input_event_rewriter_));
|
| + input_handler_manager->SetInputEventRewriter(
|
| + widget->routing_id_, copy.PassAs<InputEventRewriter>());
|
| + }
|
| +
|
| + widget->screen_info_.rect = gfx::Rect(device_size_);
|
| + widget->screen_info_.availableRect = gfx::Rect(device_size_);
|
| + widget->screen_info_.deviceScaleFactor = device_scale_factor_;
|
| +
|
| + if (widget->compositor_) {
|
| + // We keep the real device scale factor in compositor to prevent unnecessary
|
| + // scaling on browser side. This override ensures that compositor
|
| + // will not change scale factor due to WebLayerTreeView's call.
|
| + widget->compositor_->OverrideDeviceScaleFactor(
|
| + original_screen_info_.deviceScaleFactor);
|
| + }
|
| +
|
| + // In order to fit into view, WebView applies scaling transform to the
|
| + // root graphics layer.
|
| + widget->SetDeviceEmulationScale(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(
|
| + 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::DeviceEmulationHelper::OnResizeMessage(
|
| + RenderWidget* widget, 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(widget, params.overdraw_bottom_height, params.resizer_rect,
|
| + params.is_fullscreen);
|
| +
|
| + if (need_ack) {
|
| + widget->set_next_paint_is_resize_ack();
|
| + if (widget->is_accelerated_compositing_active_ && widget->compositor_)
|
| + widget->compositor_->SetNeedsRedrawRect(gfx::Rect(widget->size_));
|
| + else
|
| + widget->didInvalidateRect(gfx::Rect(widget->size_));
|
| + }
|
| +}
|
| +
|
| +void RenderWidget::DeviceEmulationHelper::OnUpdateScreenRectsMessage(
|
| + RenderWidget* widget,
|
| + 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::DeviceEmulationHelper::OnShowContextMenu(
|
| + RenderWidget* widget, ContextMenuParams* params) {
|
| + params->x *= scale_;
|
| + params->y *= scale_;
|
| +}
|
| +
|
| +WebKit::WebInputEvent* RenderWidget::DeviceEmulationHelper::ConvertInputEventToEmulated(
|
| + RenderWidget* widget, const WebKit::WebInputEvent* event) {
|
| + return input_event_rewriter_->RewriteInputEvent(event);
|
| +}
|
| +
|
| +void RenderWidget::DeviceEmulationHelper::PopupCreated(
|
| + RenderWidget* widget, RenderWidget* popup) {
|
| + popup->popup_device_emulation_helper_ = weak_ptr_factory_.GetWeakPtr();
|
| +}
|
| +
|
| +WebKit::WebRect RenderWidget::DeviceEmulationHelper::ConvertPopupScreenRectFromEmulated(
|
| + RenderWidget* popup, const WebKit::WebRect& rect) {
|
| + WebKit::WebRect result = rect;
|
| + result.x = original_view_screen_rect_.x() +
|
| + (result.x - widget_rect_.x()) * scale_;
|
| + result.y = original_view_screen_rect_.y() +
|
| + (result.y - widget_rect_.y()) * scale_;
|
| + return result;
|
| +}
|
| +
|
| } // namespace content
|
|
|