// 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::GetWeakPtr() { return weak_factory_.GetWeakPtr(); } scoped_ptr RenderWidgetHostViewBase::CreateSyntheticGestureTarget() { RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(GetRenderWidgetHost()); return scoped_ptr( new SyntheticGestureTargetBase(host)); } // Base implementation is unimplemented. void RenderWidgetHostViewBase::BeginFrameSubscription( scoped_ptr 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