| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/renderer_host/render_widget_host_view_base.h" |
| |
| #include "base/logging.h" |
| #include "build/build_config.h" |
| #include "content/browser/accessibility/browser_accessibility_manager.h" |
| #include "content/browser/gpu/gpu_data_manager_impl.h" |
| #include "content/browser/renderer_host/input/synthetic_gesture_target_base.h" |
| #include "content/browser/renderer_host/render_process_host_impl.h" |
| #include "content/browser/renderer_host/render_widget_host_delegate.h" |
| #include "content/browser/renderer_host/render_widget_host_impl.h" |
| #include "content/browser/renderer_host/render_widget_host_view_base_observer.h" |
| #include "content/common/content_switches_internal.h" |
| #include "content/public/browser/render_widget_host_view_frame_subscriber.h" |
| #include "ui/gfx/display.h" |
| #include "ui/gfx/geometry/point_conversions.h" |
| #include "ui/gfx/geometry/size_conversions.h" |
| #include "ui/gfx/geometry/size_f.h" |
| #include "ui/gfx/screen.h" |
| |
| namespace content { |
| |
| namespace { |
| |
| // How many microseconds apart input events should be flushed. |
| const int kFlushInputRateInUs = 16666; |
| |
| } |
| |
| RenderWidgetHostViewBase::RenderWidgetHostViewBase() |
| : popup_type_(blink::WebPopupTypeNone), |
| background_color_(SK_ColorWHITE), |
| mouse_locked_(false), |
| showing_context_menu_(false), |
| selection_text_offset_(0), |
| selection_range_(gfx::Range::InvalidRange()), |
| current_device_scale_factor_(0), |
| current_display_rotation_(gfx::Display::ROTATE_0), |
| pinch_zoom_enabled_(content::IsPinchToZoomEnabled()), |
| renderer_frame_number_(0), |
| weak_factory_(this) {} |
| |
| RenderWidgetHostViewBase::~RenderWidgetHostViewBase() { |
| DCHECK(!mouse_locked_); |
| // We call this here to guarantee that observers are notified before we go |
| // away. However, some subclasses may wish to call this earlier in their |
| // shutdown process, e.g. to force removal from |
| // RenderWidgetHostInputEventRouter's surface map before relinquishing a |
| // host pointer, as in RenderWidgetHostViewGuest. There is no harm in calling |
| // NotifyObserversAboutShutdown() twice, as the observers are required to |
| // de-register on the first call, and so the second call does nothing. |
| NotifyObserversAboutShutdown(); |
| } |
| |
| void RenderWidgetHostViewBase::NotifyObserversAboutShutdown() { |
| // Note: RenderWidgetHostInputEventRouter is an observer, and uses the |
| // following notification to remove this view from its surface owners map. |
| FOR_EACH_OBSERVER(RenderWidgetHostViewBaseObserver, |
| observers_, |
| OnRenderWidgetHostViewBaseDestroyed(this)); |
| // All observers are required to disconnect after they are notified. |
| DCHECK(!observers_.might_have_observers()); |
| } |
| |
| bool RenderWidgetHostViewBase::OnMessageReceived(const IPC::Message& msg){ |
| return false; |
| } |
| |
| void RenderWidgetHostViewBase::SetBackgroundColor(SkColor color) { |
| background_color_ = color; |
| } |
| |
| void RenderWidgetHostViewBase::SetBackgroundColorToDefault() { |
| SetBackgroundColor(SK_ColorWHITE); |
| } |
| |
| bool RenderWidgetHostViewBase::GetBackgroundOpaque() { |
| return SkColorGetA(background_color_) == SK_AlphaOPAQUE; |
| } |
| |
| gfx::Size RenderWidgetHostViewBase::GetPhysicalBackingSize() const { |
| gfx::Display display = |
| gfx::Screen::GetScreen()->GetDisplayNearestWindow(GetNativeView()); |
| return gfx::ScaleToCeiledSize(GetRequestedRendererSize(), |
| display.device_scale_factor()); |
| } |
| |
| bool RenderWidgetHostViewBase::DoTopControlsShrinkBlinkSize() const { |
| return false; |
| } |
| |
| float RenderWidgetHostViewBase::GetTopControlsHeight() const { |
| return 0.f; |
| } |
| |
| void RenderWidgetHostViewBase::SelectionChanged(const base::string16& text, |
| size_t offset, |
| const gfx::Range& range) { |
| selection_text_ = text; |
| selection_text_offset_ = offset; |
| selection_range_.set_start(range.start()); |
| selection_range_.set_end(range.end()); |
| } |
| |
| gfx::Size RenderWidgetHostViewBase::GetRequestedRendererSize() const { |
| return GetViewBounds().size(); |
| } |
| |
| ui::TextInputClient* RenderWidgetHostViewBase::GetTextInputClient() { |
| NOTREACHED(); |
| return NULL; |
| } |
| |
| bool RenderWidgetHostViewBase::IsShowingContextMenu() const { |
| return showing_context_menu_; |
| } |
| |
| void RenderWidgetHostViewBase::SetShowingContextMenu(bool showing) { |
| DCHECK_NE(showing_context_menu_, showing); |
| showing_context_menu_ = showing; |
| } |
| |
| base::string16 RenderWidgetHostViewBase::GetSelectedText() const { |
| if (!selection_range_.IsValid()) |
| return base::string16(); |
| return selection_text_.substr( |
| selection_range_.GetMin() - selection_text_offset_, |
| selection_range_.length()); |
| } |
| |
| bool RenderWidgetHostViewBase::IsMouseLocked() { |
| return mouse_locked_; |
| } |
| |
| InputEventAckState RenderWidgetHostViewBase::FilterInputEvent( |
| const blink::WebInputEvent& input_event) { |
| // By default, input events are simply forwarded to the renderer. |
| return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; |
| } |
| |
| void RenderWidgetHostViewBase::OnSetNeedsFlushInput() { |
| if (flush_input_timer_.IsRunning()) |
| return; |
| |
| flush_input_timer_.Start( |
| FROM_HERE, |
| base::TimeDelta::FromMicroseconds(kFlushInputRateInUs), |
| this, |
| &RenderWidgetHostViewBase::FlushInput); |
| } |
| |
| void RenderWidgetHostViewBase::WheelEventAck( |
| const blink::WebMouseWheelEvent& event, |
| InputEventAckState ack_result) { |
| } |
| |
| void RenderWidgetHostViewBase::GestureEventAck( |
| const blink::WebGestureEvent& event, |
| InputEventAckState ack_result) { |
| } |
| |
| void RenderWidgetHostViewBase::SetPopupType(blink::WebPopupType popup_type) { |
| popup_type_ = popup_type; |
| } |
| |
| blink::WebPopupType RenderWidgetHostViewBase::GetPopupType() { |
| return popup_type_; |
| } |
| |
| BrowserAccessibilityManager* |
| RenderWidgetHostViewBase::CreateBrowserAccessibilityManager( |
| BrowserAccessibilityDelegate* delegate, bool for_root_frame) { |
| NOTREACHED(); |
| return NULL; |
| } |
| |
| void RenderWidgetHostViewBase::AccessibilityShowMenu(const gfx::Point& point) { |
| RenderWidgetHostImpl* impl = NULL; |
| if (GetRenderWidgetHost()) |
| impl = RenderWidgetHostImpl::From(GetRenderWidgetHost()); |
| |
| if (impl) |
| impl->ShowContextMenuAtPoint(point); |
| } |
| |
| gfx::Point RenderWidgetHostViewBase::AccessibilityOriginInScreen( |
| const gfx::Rect& bounds) { |
| return bounds.origin(); |
| } |
| |
| gfx::AcceleratedWidget |
| RenderWidgetHostViewBase::AccessibilityGetAcceleratedWidget() { |
| return gfx::kNullAcceleratedWidget; |
| } |
| |
| gfx::NativeViewAccessible |
| RenderWidgetHostViewBase::AccessibilityGetNativeViewAccessible() { |
| return NULL; |
| } |
| |
| void RenderWidgetHostViewBase::UpdateScreenInfo(gfx::NativeView view) { |
| RenderWidgetHostImpl* impl = NULL; |
| if (GetRenderWidgetHost()) |
| impl = RenderWidgetHostImpl::From(GetRenderWidgetHost()); |
| |
| if (impl) |
| impl->delegate()->SendScreenRects(); |
| |
| if (HasDisplayPropertyChanged(view) && impl) |
| impl->NotifyScreenInfoChanged(); |
| } |
| |
| bool RenderWidgetHostViewBase::HasDisplayPropertyChanged(gfx::NativeView view) { |
| gfx::Display display = |
| gfx::Screen::GetScreen()->GetDisplayNearestWindow(view); |
| if (current_display_area_ == display.work_area() && |
| current_device_scale_factor_ == display.device_scale_factor() && |
| current_display_rotation_ == display.rotation()) { |
| return false; |
| } |
| |
| current_display_area_ = display.work_area(); |
| current_device_scale_factor_ = display.device_scale_factor(); |
| current_display_rotation_ = display.rotation(); |
| return true; |
| } |
| |
| base::WeakPtr<RenderWidgetHostViewBase> RenderWidgetHostViewBase::GetWeakPtr() { |
| return weak_factory_.GetWeakPtr(); |
| } |
| |
| scoped_ptr<SyntheticGestureTarget> |
| RenderWidgetHostViewBase::CreateSyntheticGestureTarget() { |
| RenderWidgetHostImpl* host = |
| RenderWidgetHostImpl::From(GetRenderWidgetHost()); |
| return scoped_ptr<SyntheticGestureTarget>( |
| new SyntheticGestureTargetBase(host)); |
| } |
| |
| // Base implementation is unimplemented. |
| void RenderWidgetHostViewBase::BeginFrameSubscription( |
| scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) { |
| NOTREACHED(); |
| } |
| |
| void RenderWidgetHostViewBase::EndFrameSubscription() { |
| NOTREACHED(); |
| } |
| |
| uint32_t RenderWidgetHostViewBase::RendererFrameNumber() { |
| return renderer_frame_number_; |
| } |
| |
| void RenderWidgetHostViewBase::DidReceiveRendererFrame() { |
| ++renderer_frame_number_; |
| } |
| |
| void RenderWidgetHostViewBase::FlushInput() { |
| RenderWidgetHostImpl* impl = NULL; |
| if (GetRenderWidgetHost()) |
| impl = RenderWidgetHostImpl::From(GetRenderWidgetHost()); |
| if (!impl) |
| return; |
| impl->FlushInput(); |
| } |
| |
| void RenderWidgetHostViewBase::OnTextSurroundingSelectionResponse( |
| const base::string16& content, |
| size_t start_offset, |
| size_t end_offset) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void RenderWidgetHostViewBase::ShowDisambiguationPopup( |
| const gfx::Rect& rect_pixels, |
| const SkBitmap& zoomed_bitmap) { |
| NOTIMPLEMENTED(); |
| } |
| |
| gfx::Size RenderWidgetHostViewBase::GetVisibleViewportSize() const { |
| return GetViewBounds().size(); |
| } |
| |
| void RenderWidgetHostViewBase::SetInsets(const gfx::Insets& insets) { |
| NOTIMPLEMENTED(); |
| } |
| |
| // static |
| blink::WebScreenOrientationType |
| RenderWidgetHostViewBase::GetOrientationTypeForMobile( |
| const gfx::Display& display) { |
| int angle = display.RotationAsDegree(); |
| const gfx::Rect& bounds = display.bounds(); |
| |
| // Whether the device's natural orientation is portrait. |
| bool natural_portrait = false; |
| if (angle == 0 || angle == 180) // The device is in its natural orientation. |
| natural_portrait = bounds.height() >= bounds.width(); |
| else |
| natural_portrait = bounds.height() <= bounds.width(); |
| |
| switch (angle) { |
| case 0: |
| return natural_portrait ? blink::WebScreenOrientationPortraitPrimary |
| : blink::WebScreenOrientationLandscapePrimary; |
| case 90: |
| return natural_portrait ? blink::WebScreenOrientationLandscapePrimary |
| : blink::WebScreenOrientationPortraitSecondary; |
| case 180: |
| return natural_portrait ? blink::WebScreenOrientationPortraitSecondary |
| : blink::WebScreenOrientationLandscapeSecondary; |
| case 270: |
| return natural_portrait ? blink::WebScreenOrientationLandscapeSecondary |
| : blink::WebScreenOrientationPortraitPrimary; |
| default: |
| NOTREACHED(); |
| return blink::WebScreenOrientationPortraitPrimary; |
| } |
| } |
| |
| // static |
| blink::WebScreenOrientationType |
| RenderWidgetHostViewBase::GetOrientationTypeForDesktop( |
| const gfx::Display& display) { |
| static int primary_landscape_angle = -1; |
| static int primary_portrait_angle = -1; |
| |
| int angle = display.RotationAsDegree(); |
| const gfx::Rect& bounds = display.bounds(); |
| bool is_portrait = bounds.height() >= bounds.width(); |
| |
| if (is_portrait && primary_portrait_angle == -1) |
| primary_portrait_angle = angle; |
| |
| if (!is_portrait && primary_landscape_angle == -1) |
| primary_landscape_angle = angle; |
| |
| if (is_portrait) { |
| return primary_portrait_angle == angle |
| ? blink::WebScreenOrientationPortraitPrimary |
| : blink::WebScreenOrientationPortraitSecondary; |
| } |
| |
| return primary_landscape_angle == angle |
| ? blink::WebScreenOrientationLandscapePrimary |
| : blink::WebScreenOrientationLandscapeSecondary; |
| } |
| |
| void RenderWidgetHostViewBase::OnDidNavigateMainFrameToNewPage() { |
| } |
| |
| uint32_t RenderWidgetHostViewBase::GetSurfaceIdNamespace() { |
| return 0; |
| } |
| |
| uint32_t RenderWidgetHostViewBase::SurfaceIdNamespaceAtPoint( |
| cc::SurfaceHittestDelegate* delegate, |
| const gfx::Point& point, |
| gfx::Point* transformed_point) { |
| NOTREACHED(); |
| return 0; |
| } |
| |
| gfx::Point RenderWidgetHostViewBase::TransformPointToRootCoordSpace( |
| const gfx::Point& point) { |
| return point; |
| } |
| |
| gfx::PointF RenderWidgetHostViewBase::TransformPointToRootCoordSpaceF( |
| const gfx::PointF& point) { |
| return gfx::PointF(TransformPointToRootCoordSpace( |
| gfx::ToRoundedPoint(point))); |
| } |
| |
| void RenderWidgetHostViewBase::TransformPointToLocalCoordSpace( |
| const gfx::Point& point, |
| cc::SurfaceId original_surface, |
| gfx::Point* transformed_point) { |
| *transformed_point = point; |
| } |
| |
| void RenderWidgetHostViewBase::AddObserver( |
| RenderWidgetHostViewBaseObserver* observer) { |
| observers_.AddObserver(observer); |
| } |
| |
| void RenderWidgetHostViewBase::RemoveObserver( |
| RenderWidgetHostViewBaseObserver* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| |
| cc::SurfaceId RenderWidgetHostViewBase::SurfaceIdForTesting() const { |
| return cc::SurfaceId(); |
| } |
| |
| } // namespace content |