Index: content/renderer/render_widget.cc |
=================================================================== |
--- content/renderer/render_widget.cc (revision 217537) |
+++ content/renderer/render_widget.cc (working copy) |
@@ -79,6 +79,7 @@ |
using WebKit::WebInputEvent; |
using WebKit::WebKeyboardEvent; |
using WebKit::WebMouseEvent; |
+using WebKit::WebMouseWheelEvent; |
using WebKit::WebNavigationPolicy; |
using WebKit::WebPagePopup; |
using WebKit::WebPoint; |
@@ -380,6 +381,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) |
@@ -515,6 +517,48 @@ |
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(); |
+ } |
+} |
+ |
// Got a response from the browser after the renderer decided to create a new |
// view. |
void RenderWidget::OnCreatingNewAck() { |
@@ -524,6 +568,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, |
@@ -789,6 +838,15 @@ |
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 (!input_event) { |
handling_input_event_ = false; |
return; |
@@ -1768,7 +1826,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)); |
@@ -2009,6 +2073,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())); |
@@ -2528,4 +2597,191 @@ |
return context.release(); |
} |
+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_; |
+ 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 override. |
+ widget->compositor_->OverrideDeviceScaleFactor(0.f); |
+ } |
+ widget->SetDeviceScaleFactor(original_screen_info_.deviceScaleFactor); |
+ 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) { |
+ 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); |
+ } |
+ |
+ 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)); |
+ 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())); |
+} |
+ |
+WebKit::WebInputEvent* RenderWidget::DeviceEmulationHelper::ConvertInputEventToEmulated( |
aelias_OOO_until_Jul13
2013/09/05 08:26:49
The CC impl thread captures input events as well.
dgozman
2013/09/10 19:54:02
As I understand, CC event handling is not interest
aelias_OOO_until_Jul13
2013/09/10 20:33:34
OK, I didn't notice you were only changing those s
dgozman
2013/09/10 20:55:36
Well, wrong screen position of events will conflic
aelias_OOO_until_Jul13
2013/09/10 21:00:02
should be restored back to apply backward scale.
|
+ RenderWidget* widget, 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->globalX = widget_rect_.x() + result->x; |
+ result->globalY = widget_rect_.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 RenderWidget::DeviceEmulationHelper::ConvertMouseEventToEmulated( |
+ WebKit::WebMouseEvent* event) { |
+ event->windowX = widget_rect_.x() + event->x; |
+ event->windowY = widget_rect_.y() + event->y; |
+ event->globalX = event->windowX; |
+ event->globalY = event->windowY; |
+} |
+ |
+void RenderWidget::DeviceEmulationHelper::ConvertTouchPointToEmulated( |
+ WebKit::WebTouchPoint* point) { |
+ point->screenPosition.x = widget_rect_.x() + point->position.x; |
+ point->screenPosition.y = widget_rect_.y() + point->position.y; |
+} |
+ |
+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(); |
+ result.y = original_view_screen_rect_.y() + |
+ result.y - widget_rect_.y(); |
+ return result; |
+} |
+ |
} // namespace content |