blob: d3dd8d044042810403ef4b6b09daf0ed6f1532c9 [file] [log] [blame]
// 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