Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2121)

Unified Diff: content/browser/renderer_host/render_widget_host_view_aura.cc

Issue 19681003: Fix issue where window bounds were being passed with wrong coordinates. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix issue with SetSize() adjusting the origin. Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/renderer_host/render_widget_host_view_aura.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/renderer_host/render_widget_host_view_aura.cc
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index ba4e9b1cd7b162127c8d75f8d944e5e9e9ce8935..9168c505a07f23ca3ee0e5613a76d47a75adf193 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1,3151 +1,3161 @@
-// 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_aura.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/command_line.h"
-#include "base/debug/trace_event.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "cc/output/compositor_frame.h"
-#include "cc/output/compositor_frame_ack.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
-#include "cc/resources/texture_mailbox.h"
-#include "content/browser/accessibility/browser_accessibility_manager.h"
-#include "content/browser/accessibility/browser_accessibility_state_impl.h"
-#include "content/browser/renderer_host/backing_store_aura.h"
-#include "content/browser/renderer_host/dip_util.h"
-#include "content/browser/renderer_host/overscroll_controller.h"
-#include "content/browser/renderer_host/render_view_host_delegate.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h"
-#include "content/browser/renderer_host/ui_events_helper.h"
-#include "content/browser/renderer_host/web_input_event_aura.h"
-#include "content/common/gpu/client/gl_helper.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/common/view_messages.h"
-#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
-#include "content/port/browser/render_widget_host_view_port.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/user_metrics.h"
-#include "content/public/common/content_switches.h"
-#include "media/base/video_util.h"
-#include "skia/ext/image_operations.h"
-#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "third_party/WebKit/public/web/WebScreenInfo.h"
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/client/cursor_client.h"
-#include "ui/aura/client/cursor_client_observer.h"
-#include "ui/aura/client/focus_client.h"
-#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/stacking_client.h"
-#include "ui/aura/client/tooltip_client.h"
-#include "ui/aura/client/window_types.h"
-#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_destruction_observer.h"
-#include "ui/aura/window_observer.h"
-#include "ui/aura/window_tracker.h"
-#include "ui/base/clipboard/scoped_clipboard_writer.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_utils.h"
-#include "ui/base/gestures/gesture_recognizer.h"
-#include "ui/base/hit_test.h"
-#include "ui/base/ime/input_method.h"
-#include "ui/base/ui_base_types.h"
-#include "ui/compositor/layer.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/display.h"
-#include "ui/gfx/rect_conversions.h"
-#include "ui/gfx/screen.h"
-#include "ui/gfx/size_conversions.h"
-#include "ui/gfx/skia_util.h"
-
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#include "content/browser/accessibility/browser_accessibility_manager_win.h"
-#include "content/browser/accessibility/browser_accessibility_win.h"
-#include "ui/base/win/hidden_window.h"
-#include "ui/gfx/gdi_util.h"
-#endif
-
-using gfx::RectToSkIRect;
-using gfx::SkIRectToRect;
-
-using WebKit::WebScreenInfo;
-using WebKit::WebTouchEvent;
-
-namespace content {
-namespace {
-
-// In mouse lock mode, we need to prevent the (invisible) cursor from hitting
-// the border of the view, in order to get valid movement information. However,
-// forcing the cursor back to the center of the view after each mouse move
-// doesn't work well. It reduces the frequency of useful mouse move messages
-// significantly. Therefore, we move the cursor to the center of the view only
-// if it approaches the border. |kMouseLockBorderPercentage| specifies the width
-// of the border area, in percentage of the corresponding dimension.
-const int kMouseLockBorderPercentage = 15;
-
-// When accelerated compositing is enabled and a widget resize is pending,
-// we delay further resizes of the UI. The following constant is the maximum
-// length of time that we should delay further UI resizes while waiting for a
-// resized frame from a renderer.
-const int kResizeLockTimeoutMs = 67;
-
-#if defined(OS_WIN)
-// Used to associate a plugin HWND with its RenderWidgetHostViewAura instance.
-const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner";
-
-BOOL CALLBACK WindowDestroyingCallback(HWND window, LPARAM param) {
- RenderWidgetHostViewAura* widget =
- reinterpret_cast<RenderWidgetHostViewAura*>(param);
- if (GetProp(window, kWidgetOwnerProperty) == widget) {
- // Properties set on HWNDs must be removed to avoid leaks.
- RemoveProp(window, kWidgetOwnerProperty);
- RenderWidgetHostViewBase::DetachPluginWindowsCallback(window);
- }
- return TRUE;
-}
-
-BOOL CALLBACK HideWindowsCallback(HWND window, LPARAM param) {
- RenderWidgetHostViewAura* widget =
- reinterpret_cast<RenderWidgetHostViewAura*>(param);
- if (GetProp(window, kWidgetOwnerProperty) == widget)
- SetParent(window, ui::GetHiddenWindow());
- return TRUE;
-}
-
-BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) {
- RenderWidgetHostViewAura* widget =
- reinterpret_cast<RenderWidgetHostViewAura*>(param);
-
- if (GetProp(window, kWidgetOwnerProperty) == widget) {
- HWND parent =
- widget->GetNativeView()->GetRootWindow()->GetAcceleratedWidget();
- SetParent(window, parent);
- }
- return TRUE;
-}
-
-struct CutoutRectsParams {
- RenderWidgetHostViewAura* widget;
- std::vector<gfx::Rect> cutout_rects;
- std::map<HWND, WebPluginGeometry>* geometry;
-};
-
-// Used to update the region for the windowed plugin to draw in. We start with
-// the clip rect from the renderer, then remove the cutout rects from the
-// renderer, and then remove the transient windows from the root window and the
-// constrained windows from the parent window.
-BOOL CALLBACK SetCutoutRectsCallback(HWND window, LPARAM param) {
- CutoutRectsParams* params = reinterpret_cast<CutoutRectsParams*>(param);
-
- if (GetProp(window, kWidgetOwnerProperty) == params->widget) {
- // First calculate the offset of this plugin from the root window, since
- // the cutouts are relative to the root window.
- HWND parent = params->widget->GetNativeView()->GetRootWindow()->
- GetAcceleratedWidget();
- POINT offset;
- offset.x = offset.y = 0;
- MapWindowPoints(window, parent, &offset, 1);
-
- // Now get the cached clip rect and cutouts for this plugin window that came
- // from the renderer.
- std::map<HWND, WebPluginGeometry>::iterator i = params->geometry->begin();
- while (i != params->geometry->end() &&
- i->second.window != window &&
- GetParent(i->second.window) != window) {
- ++i;
- }
-
- if (i == params->geometry->end()) {
- NOTREACHED();
- return TRUE;
- }
-
- HRGN hrgn = CreateRectRgn(i->second.clip_rect.x(),
- i->second.clip_rect.y(),
- i->second.clip_rect.right(),
- i->second.clip_rect.bottom());
- // We start with the cutout rects that came from the renderer, then add the
- // ones that came from transient and constrained windows.
- std::vector<gfx::Rect> cutout_rects = i->second.cutout_rects;
- for (size_t i = 0; i < params->cutout_rects.size(); ++i) {
- gfx::Rect offset_cutout = params->cutout_rects[i];
- offset_cutout.Offset(-offset.x, -offset.y);
- cutout_rects.push_back(offset_cutout);
- }
- gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects);
- SetWindowRgn(window, hrgn, TRUE);
- }
- return TRUE;
-}
-
-// A callback function for EnumThreadWindows to enumerate and dismiss
-// any owned popup windows.
-BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
- const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);
-
- if (::IsWindowVisible(window)) {
- const HWND owner = ::GetWindow(window, GW_OWNER);
- if (toplevel_hwnd == owner) {
- ::PostMessage(window, WM_CANCELMODE, 0, 0);
- }
- }
-
- return TRUE;
-}
-#endif
-
-void UpdateWebTouchEventAfterDispatch(WebKit::WebTouchEvent* event,
- WebKit::WebTouchPoint* point) {
- if (point->state != WebKit::WebTouchPoint::StateReleased &&
- point->state != WebKit::WebTouchPoint::StateCancelled)
- return;
- --event->touchesLength;
- for (unsigned i = point - event->touches;
- i < event->touchesLength;
- ++i) {
- event->touches[i] = event->touches[i + 1];
- }
-}
-
-bool CanRendererHandleEvent(const ui::MouseEvent* event) {
- if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
- return false;
-
-#if defined(OS_WIN)
- // Renderer cannot handle WM_XBUTTON or NC events.
- switch (event->native_event().message) {
- case WM_XBUTTONDOWN:
- case WM_XBUTTONUP:
- case WM_XBUTTONDBLCLK:
- case WM_NCMOUSELEAVE:
- case WM_NCMOUSEMOVE:
- case WM_NCXBUTTONDOWN:
- case WM_NCXBUTTONUP:
- case WM_NCXBUTTONDBLCLK:
- return false;
- default:
- break;
- }
-#endif
- return true;
-}
-
-// We don't mark these as handled so that they're sent back to the
-// DefWindowProc so it can generate WM_APPCOMMAND as necessary.
-bool IsXButtonUpEvent(const ui::MouseEvent* event) {
-#if defined(OS_WIN)
- switch (event->native_event().message) {
- case WM_XBUTTONUP:
- case WM_NCXBUTTONUP:
- return true;
- }
-#endif
- return false;
-}
-
-void GetScreenInfoForWindow(WebScreenInfo* results, aura::Window* window) {
- const gfx::Display display = window ?
- gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window) :
- gfx::Screen::GetScreenFor(window)->GetPrimaryDisplay();
- results->rect = display.bounds();
- results->availableRect = display.work_area();
- // TODO(derat|oshima): Don't hardcode this. Get this from display object.
- results->depth = 24;
- results->depthPerComponent = 8;
- results->deviceScaleFactor = display.device_scale_factor();
-}
-
-bool ShouldSendPinchGesture() {
-#if defined(OS_WIN)
- if (base::win::GetVersion() >= base::win::VERSION_WIN8)
- return true;
-#endif
- static bool pinch_allowed =
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableViewport) ||
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePinch);
- return pinch_allowed;
-}
-
-bool PointerEventActivates(const ui::Event& event) {
- if (event.type() == ui::ET_MOUSE_PRESSED)
- return true;
-
- if (event.type() == ui::ET_GESTURE_BEGIN) {
- const ui::GestureEvent& gesture =
- static_cast<const ui::GestureEvent&>(event);
- return gesture.details().touch_points() == 1;
- }
-
- return false;
-}
-
-// Swap ack for the renderer when kCompositeToMailbox is enabled.
-void SendCompositorFrameAck(
- int32 route_id,
- uint32 output_surface_id,
- int renderer_host_id,
- const gpu::Mailbox& received_mailbox,
- const gfx::Size& received_size,
- bool skip_frame,
- const scoped_refptr<ui::Texture>& texture_to_produce) {
- cc::CompositorFrameAck ack;
- ack.gl_frame_data.reset(new cc::GLFrameData());
- DCHECK(!texture_to_produce.get() || !skip_frame);
- if (texture_to_produce.get()) {
- std::string mailbox_name = texture_to_produce->Produce();
- std::copy(mailbox_name.data(),
- mailbox_name.data() + mailbox_name.length(),
- reinterpret_cast<char*>(ack.gl_frame_data->mailbox.name));
- ack.gl_frame_data->size = texture_to_produce->size();
- ack.gl_frame_data->sync_point =
- content::ImageTransportFactory::GetInstance()->InsertSyncPoint();
- } else if (skip_frame) {
- // Skip the frame, i.e. tell the producer to reuse the same buffer that
- // we just received.
- ack.gl_frame_data->size = received_size;
- ack.gl_frame_data->mailbox = received_mailbox;
- }
-
- RenderWidgetHostImpl::SendSwapCompositorFrameAck(
- route_id, output_surface_id, renderer_host_id, ack);
-}
-
-void AcknowledgeBufferForGpu(
- int32 route_id,
- int gpu_host_id,
- const std::string& received_mailbox,
- bool skip_frame,
- const scoped_refptr<ui::Texture>& texture_to_produce) {
- AcceleratedSurfaceMsg_BufferPresented_Params ack;
- uint32 sync_point = 0;
- DCHECK(!texture_to_produce.get() || !skip_frame);
- if (texture_to_produce.get()) {
- ack.mailbox_name = texture_to_produce->Produce();
- sync_point =
- content::ImageTransportFactory::GetInstance()->InsertSyncPoint();
- } else if (skip_frame) {
- ack.mailbox_name = received_mailbox;
- ack.sync_point = 0;
- }
-
- ack.sync_point = sync_point;
- RenderWidgetHostImpl::AcknowledgeBufferPresent(
- route_id, gpu_host_id, ack);
-}
-
-void ReleaseMailbox(scoped_ptr<base::SharedMemory> shared_memory,
- base::Callback<void()> callback,
- unsigned sync_point, bool lost_resource) {
- callback.Run();
-}
-
-} // namespace
-
-// We need to watch for mouse events outside a Web Popup or its parent
-// and dismiss the popup for certain events.
-class RenderWidgetHostViewAura::EventFilterForPopupExit :
- public ui::EventHandler {
- public:
- explicit EventFilterForPopupExit(RenderWidgetHostViewAura* rwhva)
- : rwhva_(rwhva) {
- DCHECK(rwhva_);
- aura::RootWindow* root_window = rwhva_->window_->GetRootWindow();
- DCHECK(root_window);
- root_window->AddPreTargetHandler(this);
- }
-
- virtual ~EventFilterForPopupExit() {
- aura::RootWindow* root_window = rwhva_->window_->GetRootWindow();
- DCHECK(root_window);
- root_window->RemovePreTargetHandler(this);
- }
-
- // Overridden from ui::EventHandler
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
- rwhva_->ApplyEventFilterForPopupExit(event);
- }
-
- private:
- RenderWidgetHostViewAura* rwhva_;
-
- DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit);
-};
-
-void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
- ui::MouseEvent* event) {
- if (in_shutdown_ || is_fullscreen_)
- return;
-
- if (event->type() != ui::ET_MOUSE_PRESSED || !event->target())
- return;
-
- aura::Window* target = static_cast<aura::Window*>(event->target());
- if (target != window_ &&
- (!popup_parent_host_view_ ||
- target != popup_parent_host_view_->window_)) {
- // Note: popup_parent_host_view_ may be NULL when there are multiple
- // popup children per view. See: RenderWidgetHostViewAura::InitAsPopup().
- in_shutdown_ = true;
- host_->Shutdown();
- }
-}
-
-// We have to implement the WindowObserver interface on a separate object
-// because clang doesn't like implementing multiple interfaces that have
-// methods with the same name. This object is owned by the
-// RenderWidgetHostViewAura.
-class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver {
- public:
- explicit WindowObserver(RenderWidgetHostViewAura* view)
- : view_(view) {
- view_->window_->AddObserver(this);
- }
-
- virtual ~WindowObserver() {
- view_->window_->RemoveObserver(this);
- }
-
- // Overridden from aura::WindowObserver:
- virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
- if (window == view_->window_)
- view_->AddedToRootWindow();
- }
-
- virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE {
- if (window == view_->window_)
- view_->RemovingFromRootWindow();
- }
-
- private:
- RenderWidgetHostViewAura* view_;
-
- DISALLOW_COPY_AND_ASSIGN(WindowObserver);
-};
-
-#if defined(OS_WIN)
-// On Windows, we need to watch the top level window for changes to transient
-// windows because they can cover the view and we need to ensure that they're
-// rendered on top of windowed NPAPI plugins.
-class RenderWidgetHostViewAura::TransientWindowObserver
- : public aura::WindowObserver {
- public:
- explicit TransientWindowObserver(RenderWidgetHostViewAura* view)
- : view_(view), top_level_(NULL) {
- view_->window_->AddObserver(this);
- }
-
- virtual ~TransientWindowObserver() {
- view_->window_->RemoveObserver(this);
- StopObserving();
- }
-
- // Overridden from aura::WindowObserver:
- virtual void OnWindowHierarchyChanged(
- const aura::WindowObserver::HierarchyChangeParams& params) OVERRIDE {
- aura::Window* top_level = GetToplevelWindow();
- if (top_level == top_level_)
- return;
-
- StopObserving();
- top_level_ = top_level;
- if (top_level_ && top_level_ != view_->window_)
- top_level_->AddObserver(this);
- }
-
- virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
- if (window == top_level_)
- StopObserving();
- }
-
- virtual void OnWindowBoundsChanged(aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) OVERRIDE {
- if (window->transient_parent())
- SendPluginCutoutRects();
- }
-
- virtual void OnWindowVisibilityChanged(aura::Window* window,
- bool visible) OVERRIDE {
- if (window->transient_parent())
- SendPluginCutoutRects();
- }
-
- virtual void OnAddTransientChild(aura::Window* window,
- aura::Window* transient) OVERRIDE {
- transient->AddObserver(this);
- // Just wait for the OnWindowBoundsChanged of the transient, since the size
- // is not known now.
- }
-
- virtual void OnRemoveTransientChild(aura::Window* window,
- aura::Window* transient) OVERRIDE {
- transient->RemoveObserver(this);
- SendPluginCutoutRects();
- }
-
- aura::Window* GetToplevelWindow() {
- aura::RootWindow* root = view_->window_->GetRootWindow();
- if (!root)
- return NULL;
- aura::client::ActivationClient* activation_client =
- aura::client::GetActivationClient(root);
- if (!activation_client)
- return NULL;
- return activation_client->GetToplevelWindow(view_->window_);
- }
-
- void StopObserving() {
- if (!top_level_)
- return;
-
- const aura::Window::Windows& transients = top_level_->transient_children();
- for (size_t i = 0; i < transients.size(); ++i)
- transients[i]->RemoveObserver(this);
-
- if (top_level_ != view_->window_)
- top_level_->RemoveObserver(this);
- top_level_ = NULL;
- }
-
- void SendPluginCutoutRects() {
- std::vector<gfx::Rect> cutouts;
- if (top_level_) {
- const aura::Window::Windows& transients =
- top_level_->transient_children();
- for (size_t i = 0; i < transients.size(); ++i) {
- if (transients[i]->IsVisible())
- cutouts.push_back(transients[i]->GetBoundsInRootWindow());
- }
- }
-
- view_->UpdateTransientRects(cutouts);
- }
- private:
- RenderWidgetHostViewAura* view_;
- aura::Window* top_level_;
-
- DISALLOW_COPY_AND_ASSIGN(TransientWindowObserver);
-};
-
-#endif
-
-class RenderWidgetHostViewAura::ResizeLock {
- public:
- ResizeLock(aura::RootWindow* root_window,
- const gfx::Size new_size,
- bool defer_compositor_lock)
- : root_window_(root_window),
- new_size_(new_size),
- compositor_lock_(defer_compositor_lock ?
- NULL :
- root_window_->compositor()->GetCompositorLock()),
- weak_ptr_factory_(this),
- defer_compositor_lock_(defer_compositor_lock) {
- TRACE_EVENT_ASYNC_BEGIN2("ui", "ResizeLock", this,
- "width", new_size_.width(),
- "height", new_size_.height());
- root_window_->HoldPointerMoves();
-
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&RenderWidgetHostViewAura::ResizeLock::CancelLock,
- weak_ptr_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs));
- }
-
- ~ResizeLock() {
- CancelLock();
- TRACE_EVENT_ASYNC_END2("ui", "ResizeLock", this,
- "width", new_size_.width(),
- "height", new_size_.height());
- }
-
- void UnlockCompositor() {
- defer_compositor_lock_ = false;
- compositor_lock_ = NULL;
- }
-
- void CancelLock() {
- if (!root_window_)
- return;
- UnlockCompositor();
- root_window_->ReleasePointerMoves();
- root_window_ = NULL;
- }
-
- const gfx::Size& expected_size() const {
- return new_size_;
- }
-
- bool GrabDeferredLock() {
- if (root_window_ && defer_compositor_lock_) {
- compositor_lock_ = root_window_->compositor()->GetCompositorLock();
- defer_compositor_lock_ = false;
- return true;
- }
- return false;
- }
-
- private:
- aura::RootWindow* root_window_;
- gfx::Size new_size_;
- scoped_refptr<ui::CompositorLock> compositor_lock_;
- base::WeakPtrFactory<ResizeLock> weak_ptr_factory_;
- bool defer_compositor_lock_;
-
- DISALLOW_COPY_AND_ASSIGN(ResizeLock);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, public:
-
-RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
- : host_(RenderWidgetHostImpl::From(host)),
- window_(new aura::Window(this)),
- in_shutdown_(false),
- is_fullscreen_(false),
- popup_parent_host_view_(NULL),
- popup_child_host_view_(NULL),
- is_loading_(false),
- text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
- can_compose_inline_(true),
- has_composition_text_(false),
- last_swapped_surface_scale_factor_(1.f),
- paint_canvas_(NULL),
- synthetic_move_sent_(false),
- accelerated_compositing_state_changed_(false),
- can_lock_compositor_(YES),
- cursor_visibility_state_in_renderer_(UNKNOWN),
- paint_observer_(NULL),
- touch_editing_client_(NULL) {
- host_->SetView(this);
- window_observer_.reset(new WindowObserver(this));
- aura::client::SetTooltipText(window_, &tooltip_);
- aura::client::SetActivationDelegate(window_, this);
- aura::client::SetActivationChangeObserver(window_, this);
- aura::client::SetFocusChangeObserver(window_, this);
- gfx::Screen::GetScreenFor(window_)->AddObserver(this);
-#if defined(OS_WIN)
- transient_observer_.reset(new TransientWindowObserver(this));
-#endif
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, RenderWidgetHostView implementation:
-
-void RenderWidgetHostViewAura::InitAsChild(
- gfx::NativeView parent_view) {
- window_->Init(ui::LAYER_TEXTURED);
- window_->SetName("RenderWidgetHostViewAura");
-}
-
-void RenderWidgetHostViewAura::InitAsPopup(
- RenderWidgetHostView* parent_host_view,
- const gfx::Rect& bounds_in_screen) {
- popup_parent_host_view_ =
- static_cast<RenderWidgetHostViewAura*>(parent_host_view);
-
- RenderWidgetHostViewAura* old_child =
- popup_parent_host_view_->popup_child_host_view_;
- if (old_child) {
- // TODO(jhorwich): Allow multiple popup_child_host_view_ per view, or
- // similar mechanism to ensure a second popup doesn't cause the first one
- // to never get a chance to filter events. See crbug.com/160589.
- DCHECK(old_child->popup_parent_host_view_ == popup_parent_host_view_);
- old_child->popup_parent_host_view_ = NULL;
- }
- popup_parent_host_view_->popup_child_host_view_ = this;
- window_->SetType(aura::client::WINDOW_TYPE_MENU);
- window_->Init(ui::LAYER_TEXTURED);
- window_->SetName("RenderWidgetHostViewAura");
-
- aura::RootWindow* root = popup_parent_host_view_->window_->GetRootWindow();
- window_->SetDefaultParentByRootWindow(root, bounds_in_screen);
-
- // TODO(erg): While I could make sure details of the StackingClient are
- // hidden behind aura, hiding the details of the ScreenPositionClient will
- // take another effort.
- aura::client::ScreenPositionClient* screen_position_client =
- aura::client::GetScreenPositionClient(root);
- gfx::Point origin_in_parent(bounds_in_screen.origin());
- if (screen_position_client) {
- screen_position_client->ConvertPointFromScreen(
- window_->parent(), &origin_in_parent);
- }
- SetBounds(gfx::Rect(origin_in_parent, bounds_in_screen.size()));
- Show();
-}
-
-void RenderWidgetHostViewAura::InitAsFullscreen(
- RenderWidgetHostView* reference_host_view) {
- is_fullscreen_ = true;
- window_->SetType(aura::client::WINDOW_TYPE_NORMAL);
- window_->Init(ui::LAYER_TEXTURED);
- window_->SetName("RenderWidgetHostViewAura");
- window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
-
- aura::RootWindow* parent = NULL;
- gfx::Rect bounds;
- if (reference_host_view) {
- aura::Window* reference_window =
- static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_;
- if (reference_window) {
- host_tracker_.reset(new aura::WindowTracker);
- host_tracker_->Add(reference_window);
- }
- gfx::Display display = gfx::Screen::GetScreenFor(window_)->
- GetDisplayNearestWindow(reference_window);
- parent = reference_window->GetRootWindow();
- bounds = display.bounds();
- }
- window_->SetDefaultParentByRootWindow(parent, bounds);
- Show();
- Focus();
-}
-
-RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
- return host_;
-}
-
-void RenderWidgetHostViewAura::WasShown() {
- if (!host_->is_hidden())
- return;
- host_->WasShown();
-
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(window_->GetRootWindow());
- if (cursor_client)
- NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
-
- if (!current_surface_.get() && host_->is_accelerated_compositing_active() &&
- !released_front_lock_.get()) {
- released_front_lock_ = GetCompositor()->GetCompositorLock();
- }
-
-#if defined(OS_WIN)
- LPARAM lparam = reinterpret_cast<LPARAM>(this);
- EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
- transient_observer_->SendPluginCutoutRects();
-#endif
-}
-
-void RenderWidgetHostViewAura::WasHidden() {
- if (host_->is_hidden())
- return;
- host_->WasHidden();
-
- released_front_lock_ = NULL;
-
-#if defined(OS_WIN)
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (root_window) {
- HWND parent = root_window->GetAcceleratedWidget();
- LPARAM lparam = reinterpret_cast<LPARAM>(this);
-
- EnumChildWindows(parent, HideWindowsCallback, lparam);
- }
-#endif
-}
-
-void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) {
- SetBounds(gfx::Rect(window_->bounds().origin(), size));
-}
-
-void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
- if (HasDisplayPropertyChanged(window_))
- host_->InvalidateScreenInfo();
-
- window_->SetBounds(rect);
- host_->WasResized();
- MaybeCreateResizeLock();
- if (touch_editing_client_) {
- touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
- selection_focus_rect_);
- }
-}
-
-void RenderWidgetHostViewAura::MaybeCreateResizeLock() {
- gfx::Size desired_size = window_->bounds().size();
- if (!host_->should_auto_resize() &&
- !resize_lock_.get() &&
- desired_size != current_frame_size_ &&
- host_->is_accelerated_compositing_active()) {
- aura::RootWindow* root_window = window_->GetRootWindow();
- ui::Compositor* compositor = root_window ?
- root_window->compositor() : NULL;
- if (root_window && compositor) {
- // Listen to changes in the compositor lock state.
- if (!compositor->HasObserver(this))
- compositor->AddObserver(this);
-
-// On Windows while resizing, the the resize locks makes us mis-paint a white
-// vertical strip (including the non-client area) if the content composition is
-// lagging the UI composition. So here we disable the throttling so that the UI
-// bits can draw ahead of the content thereby reducing the amount of whiteout.
-// Because this causes the content to be drawn at wrong sizes while resizing
-// we compensate by blocking the UI thread in Compositor::Draw() by issuing a
-// FinishAllRendering() if we are resizing.
-#if !defined (OS_WIN)
- bool defer_compositor_lock =
- can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
- can_lock_compositor_ == NO_PENDING_COMMIT;
-
- if (can_lock_compositor_ == YES)
- can_lock_compositor_ = YES_DID_LOCK;
-
- resize_lock_.reset(new ResizeLock(root_window, desired_size,
- defer_compositor_lock));
-#endif
- }
- }
-}
-
-gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
- return window_;
-}
-
-gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const {
-#if defined(OS_WIN)
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (root_window) {
- HWND window = root_window->GetAcceleratedWidget();
- return reinterpret_cast<gfx::NativeViewId>(window);
- }
-#endif
- return static_cast<gfx::NativeViewId>(NULL);
-}
-
-gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
-#if defined(OS_WIN)
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (!root_window)
- return static_cast<gfx::NativeViewAccessible>(NULL);
- HWND hwnd = root_window->GetAcceleratedWidget();
-
- BrowserAccessibilityManager* manager =
- GetOrCreateBrowserAccessibilityManager();
- if (manager)
- return manager->GetRoot()->ToBrowserAccessibilityWin();
-#endif
-
- NOTIMPLEMENTED();
- return static_cast<gfx::NativeViewAccessible>(NULL);
-}
-
-BrowserAccessibilityManager*
-RenderWidgetHostViewAura::GetOrCreateBrowserAccessibilityManager() {
- BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
- if (manager)
- return manager;
-
-#if defined(OS_WIN)
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (!root_window)
- return NULL;
- HWND hwnd = root_window->GetAcceleratedWidget();
-
- // The accessible_parent may be NULL at this point. The WebContents will pass
- // it down to this instance (by way of the RenderViewHost and
- // RenderWidgetHost) when it is known. This instance will then set it on its
- // BrowserAccessibilityManager.
- gfx::NativeViewAccessible accessible_parent =
- host_->GetParentNativeViewAccessible();
-
- manager = new BrowserAccessibilityManagerWin(
- hwnd, accessible_parent,
- BrowserAccessibilityManagerWin::GetEmptyDocument(), this);
-#else
- manager = BrowserAccessibilityManager::Create(
- BrowserAccessibilityManager::GetEmptyDocument(), this);
-#endif
-
- SetBrowserAccessibilityManager(manager);
- return manager;
-}
-
-void RenderWidgetHostViewAura::MovePluginWindows(
- const gfx::Vector2d& scroll_offset,
- const std::vector<WebPluginGeometry>& plugin_window_moves) {
-#if defined(OS_WIN)
- // We need to clip the rectangle to the tab's viewport, otherwise we will draw
- // over the browser UI.
- if (!window_->GetRootWindow()) {
- DCHECK(plugin_window_moves.empty());
- return;
- }
- HWND parent = window_->GetRootWindow()->GetAcceleratedWidget();
- gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
- std::vector<WebPluginGeometry> moves = plugin_window_moves;
-
- gfx::Rect view_port(scroll_offset.x(), scroll_offset.y(), view_bounds.width(),
- view_bounds.height());
-
- for (size_t i = 0; i < moves.size(); ++i) {
- gfx::Rect clip(moves[i].clip_rect);
- gfx::Vector2d view_port_offset(
- moves[i].window_rect.OffsetFromOrigin() + scroll_offset);
- clip.Offset(view_port_offset);
- clip.Intersect(view_port);
- clip.Offset(-view_port_offset);
- moves[i].clip_rect = clip;
-
- moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin());
-
- plugin_window_moves_[moves[i].window] = moves[i];
-
- // transient_rects_ and constrained_rects_ are relative to the root window.
- // We want to convert them to be relative to the plugin window.
- std::vector<gfx::Rect> cutout_rects;
- cutout_rects.assign(transient_rects_.begin(), transient_rects_.end());
- cutout_rects.insert(cutout_rects.end(), constrained_rects_.begin(),
- constrained_rects_.end());
- for (size_t j = 0; j < cutout_rects.size(); ++j) {
- gfx::Rect offset_cutout = cutout_rects[j];
- offset_cutout -= moves[i].window_rect.OffsetFromOrigin();
- moves[i].cutout_rects.push_back(offset_cutout);
- }
- }
-
- MovePluginWindowsHelper(parent, moves);
-
- // Make sure each plugin window (or its wrapper if it exists) has a pointer to
- // |this|.
- for (size_t i = 0; i < moves.size(); ++i) {
- HWND window = moves[i].window;
- if (GetParent(window) != parent) {
- window = GetParent(window);
- DCHECK(GetParent(window) == parent);
- }
- if (!GetProp(window, kWidgetOwnerProperty))
- CHECK(SetProp(window, kWidgetOwnerProperty, this));
- }
-#endif // defined(OS_WIN)
-}
-
-void RenderWidgetHostViewAura::Focus() {
- // Make sure we have a FocusClient before attempting to Focus(). In some
- // situations we may not yet be in a valid Window hierarchy (such as reloading
- // after out of memory discarded the tab).
- aura::client::FocusClient* client = aura::client::GetFocusClient(window_);
- if (client)
- window_->Focus();
-}
-
-void RenderWidgetHostViewAura::Blur() {
- window_->Blur();
-}
-
-bool RenderWidgetHostViewAura::HasFocus() const {
- return window_->HasFocus();
-}
-
-bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
- return window_->layer()->has_external_content() ||
- !!host_->GetBackingStore(false);
-}
-
-void RenderWidgetHostViewAura::Show() {
- window_->Show();
-}
-
-void RenderWidgetHostViewAura::Hide() {
- window_->Hide();
-}
-
-bool RenderWidgetHostViewAura::IsShowing() {
- return window_->IsVisible();
-}
-
-gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
- // This is the size that we want the renderer to produce. While we're waiting
- // for the correct frame (i.e. during a resize), don't change the size so that
- // we don't pipeline more resizes than we can handle.
- gfx::Rect bounds(window_->GetBoundsInScreen());
- if (resize_lock_.get())
- return gfx::Rect(bounds.origin(), resize_lock_->expected_size());
- else
- return bounds;
-}
-
-void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) {
- RenderWidgetHostViewBase::SetBackground(background);
- host_->SetBackground(background);
- window_->layer()->SetFillsBoundsOpaquely(background.isOpaque());
-}
-
-#if defined(OS_WIN)
-gfx::NativeViewAccessible
-RenderWidgetHostViewAura::AccessibleObjectFromChildId(long child_id) {
- BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
- if (!manager)
- return NULL;
-
- return manager->ToBrowserAccessibilityManagerWin()->GetFromUniqueIdWin(
- child_id);
-}
-#endif // defined(OS_WIN)
-
-void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
- current_cursor_ = cursor;
- const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
- GetDisplayNearestWindow(window_);
- current_cursor_.SetDeviceScaleFactor(display.device_scale_factor());
- UpdateCursorIfOverSelf();
-}
-
-void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
- if (is_loading_ && !is_loading && paint_observer_)
- paint_observer_->OnPageLoadComplete();
- is_loading_ = is_loading;
- UpdateCursorIfOverSelf();
-}
-
-void RenderWidgetHostViewAura::TextInputTypeChanged(
- ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
- if (text_input_type_ != type ||
- can_compose_inline_ != can_compose_inline) {
- text_input_type_ = type;
- can_compose_inline_ = can_compose_inline;
- if (GetInputMethod())
- GetInputMethod()->OnTextInputTypeChanged(this);
- if (touch_editing_client_)
- touch_editing_client_->OnTextInputTypeChanged(text_input_type_);
- }
-}
-
-void RenderWidgetHostViewAura::ImeCancelComposition() {
- if (GetInputMethod())
- GetInputMethod()->CancelComposition(this);
- has_composition_text_ = false;
-}
-
-void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
- const ui::Range& range,
- const std::vector<gfx::Rect>& character_bounds) {
- composition_character_bounds_ = character_bounds;
-}
-
-void RenderWidgetHostViewAura::DidUpdateBackingStore(
- const gfx::Rect& scroll_rect,
- const gfx::Vector2d& scroll_delta,
- const std::vector<gfx::Rect>& copy_rects,
- const ui::LatencyInfo& latency_info) {
- if (accelerated_compositing_state_changed_)
- UpdateExternalTexture();
-
- software_latency_info_.MergeWith(latency_info);
-
- // Use the state of the RenderWidgetHost and not the window as the two may
- // differ. In particular if the window is hidden but the renderer isn't and we
- // ignore the update and the window is made visible again the layer isn't
- // marked as dirty and we show the wrong thing.
- // We do this after UpdateExternalTexture() so that when we become visible
- // we're not drawing a stale texture.
- if (host_->is_hidden())
- return;
-
- gfx::Rect clip_rect;
- if (paint_canvas_) {
- SkRect sk_clip_rect;
- if (paint_canvas_->sk_canvas()->getClipBounds(&sk_clip_rect))
- clip_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(sk_clip_rect));
- }
-
- if (!scroll_rect.IsEmpty())
- SchedulePaintIfNotInClip(scroll_rect, clip_rect);
-
-#if defined(OS_WIN)
- aura::RootWindow* root_window = window_->GetRootWindow();
-#endif
- for (size_t i = 0; i < copy_rects.size(); ++i) {
- gfx::Rect rect = gfx::SubtractRects(copy_rects[i], scroll_rect);
- if (rect.IsEmpty())
- continue;
-
- SchedulePaintIfNotInClip(rect, clip_rect);
-
-#if defined(OS_WIN)
- if (root_window) {
- // Send the invalid rect in screen coordinates.
- gfx::Rect screen_rect = GetViewBounds();
- gfx::Rect invalid_screen_rect(rect);
- invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y());
- HWND hwnd = root_window->GetAcceleratedWidget();
- PaintPluginWindowsHelper(hwnd, invalid_screen_rect);
- }
-#endif // defined(OS_WIN)
- }
-}
-
-void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
- int error_code) {
- UpdateCursorIfOverSelf();
- Destroy();
-}
-
-void RenderWidgetHostViewAura::Destroy() {
- // Beware, this function is not called on all destruction paths. It will
- // implicitly end up calling ~RenderWidgetHostViewAura though, so all
- // destruction/cleanup code should happen there, not here.
- in_shutdown_ = true;
- delete window_;
-}
-
-void RenderWidgetHostViewAura::SetTooltipText(const string16& tooltip_text) {
- tooltip_ = tooltip_text;
- aura::RootWindow* root_window = window_->GetRootWindow();
- aura::client::TooltipClient* tooltip_client =
- aura::client::GetTooltipClient(root_window);
- if (tooltip_client) {
- tooltip_client->UpdateTooltip(window_);
- // Content tooltips should be visible indefinitely.
- tooltip_client->SetTooltipShownTimeout(window_, 0);
- }
-}
-
-void RenderWidgetHostViewAura::SelectionChanged(const string16& text,
- size_t offset,
- const ui::Range& range) {
- RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
-
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
- if (text.empty() || range.is_empty())
- return;
-
- // Set the BUFFER_SELECTION to the ui::Clipboard.
- ui::ScopedClipboardWriter clipboard_writer(
- ui::Clipboard::GetForCurrentThread(),
- ui::Clipboard::BUFFER_SELECTION);
- clipboard_writer.WriteText(text);
-#endif // defined(USE_X11) && !defined(OS_CHROMEOS)
-}
-
-void RenderWidgetHostViewAura::SelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params) {
- if (selection_anchor_rect_ == params.anchor_rect &&
- selection_focus_rect_ == params.focus_rect)
- return;
-
- selection_anchor_rect_ = params.anchor_rect;
- selection_focus_rect_ = params.focus_rect;
-
- if (GetInputMethod())
- GetInputMethod()->OnCaretBoundsChanged(this);
-
- if (touch_editing_client_) {
- touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
- selection_focus_rect_);
- }
-}
-
-void RenderWidgetHostViewAura::ScrollOffsetChanged() {
- aura::RootWindow* root = window_->GetRootWindow();
- if (!root)
- return;
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(root);
- if (cursor_client && !cursor_client->IsCursorVisible())
- cursor_client->DisableMouseEvents();
-}
-
-BackingStore* RenderWidgetHostViewAura::AllocBackingStore(
- const gfx::Size& size) {
- return new BackingStoreAura(host_, size);
-}
-
-void RenderWidgetHostViewAura::CopyFromCompositingSurface(
- const gfx::Rect& src_subrect,
- const gfx::Size& dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback) {
- if (!window_->layer()->has_external_content()) {
- callback.Run(false, SkBitmap());
- return;
- }
-
- const gfx::Size& dst_size_in_pixel = ConvertViewSizeToPixel(this, dst_size);
- scoped_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateRequest(base::Bind(
- &RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult,
- dst_size_in_pixel,
- callback));
- request->set_area(src_subrect);
- window_->layer()->RequestCopyOfOutput(request.Pass());
-}
-
-void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
- const gfx::Rect& src_subrect,
- const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback) {
- if (!window_->layer()->has_external_content()) {
- callback.Run(false);
- return;
- }
-
- scoped_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateRequest(base::Bind(
- &RenderWidgetHostViewAura::
- CopyFromCompositingSurfaceHasResultForVideo,
- AsWeakPtr(), // For caching the ReadbackYUVInterface on this class.
- target,
- callback));
- request->set_area(src_subrect);
- window_->layer()->RequestCopyOfOutput(request.Pass());
-}
-
-bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
- // TODO(skaslev): Implement this path for s/w compositing.
- return window_->layer()->has_external_content() &&
- host_->is_accelerated_compositing_active();
-}
-
-bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
- return true;
-}
-
-void RenderWidgetHostViewAura::BeginFrameSubscription(
- scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
- frame_subscriber_ = subscriber.Pass();
-}
-
-void RenderWidgetHostViewAura::EndFrameSubscription() {
- frame_subscriber_.reset();
-}
-
-
-void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() {
- // Delay processing the state change until we either get a software frame if
- // switching to software mode or receive a buffers swapped notification
- // if switching to accelerated mode.
- // Sometimes (e.g. on a page load) the renderer will spuriously disable then
- // re-enable accelerated compositing, causing us to flash.
- // TODO(piman): factor the enable/disable accelerated compositing message into
- // the UpdateRect/AcceleratedSurfaceBuffersSwapped messages so that we have
- // fewer inconsistent temporary states.
- accelerated_compositing_state_changed_ = true;
-}
-
-bool RenderWidgetHostViewAura::ShouldSkipFrame(gfx::Size size_in_dip) const {
- if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
- can_lock_compositor_ == NO_PENDING_COMMIT ||
- !resize_lock_.get())
- return false;
-
- return size_in_dip != resize_lock_->expected_size();
-}
-
-void RenderWidgetHostViewAura::CheckResizeLock() {
- if (!resize_lock_ || resize_lock_->expected_size() != current_frame_size_)
- return;
-
- // Since we got the size we were looking for, unlock the compositor. But delay
- // the release of the lock until we've kicked a frame with the new texture, to
- // avoid resizing the UI before we have a chance to draw a "good" frame.
- resize_lock_->UnlockCompositor();
- ui::Compositor* compositor = GetCompositor();
- if (compositor) {
- if (!compositor->HasObserver(this))
- compositor->AddObserver(this);
- }
-}
-
-void RenderWidgetHostViewAura::UpdateExternalTexture() {
- // Delay processing accelerated compositing state change till here where we
- // act upon the state change. (Clear the external texture if switching to
- // software mode or set the external texture if going to accelerated mode).
- if (accelerated_compositing_state_changed_)
- accelerated_compositing_state_changed_ = false;
-
- bool is_compositing_active = host_->is_accelerated_compositing_active();
- if (is_compositing_active && current_surface_.get()) {
- window_->layer()->SetExternalTexture(current_surface_.get());
- current_frame_size_ = ConvertSizeToDIP(
- current_surface_->device_scale_factor(), current_surface_->size());
- CheckResizeLock();
- } else if (is_compositing_active &&
- current_software_frame_.IsSharedMemory()) {
- window_->layer()->SetTextureMailbox(current_software_frame_,
- last_swapped_surface_scale_factor_);
- current_frame_size_ = ConvertSizeToDIP(
- last_swapped_surface_scale_factor_,
- current_software_frame_.shared_memory_size());
- CheckResizeLock();
- } else {
- window_->layer()->SetExternalTexture(NULL);
- resize_lock_.reset();
- host_->WasResized();
- }
-}
-
-bool RenderWidgetHostViewAura::SwapBuffersPrepare(
- const gfx::Rect& surface_rect,
- float surface_scale_factor,
- const gfx::Rect& damage_rect,
- const std::string& mailbox_name,
- const BufferPresentedCallback& ack_callback) {
- if (last_swapped_surface_size_ != surface_rect.size()) {
- // The surface could have shrunk since we skipped an update, in which
- // case we can expect a full update.
- DLOG_IF(ERROR, damage_rect != surface_rect) << "Expected full damage rect";
- skipped_damage_.setEmpty();
- last_swapped_surface_size_ = surface_rect.size();
- last_swapped_surface_scale_factor_ = surface_scale_factor;
- }
-
- if (ShouldSkipFrame(ConvertSizeToDIP(surface_scale_factor,
- surface_rect.size())) ||
- mailbox_name.empty()) {
- skipped_damage_.op(RectToSkIRect(damage_rect), SkRegion::kUnion_Op);
- ack_callback.Run(true, scoped_refptr<ui::Texture>());
- return false;
- }
-
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- current_surface_ =
- factory->CreateTransportClient(surface_scale_factor);
- if (!current_surface_.get()) {
- LOG(ERROR) << "Failed to create ImageTransport texture";
- ack_callback.Run(true, scoped_refptr<ui::Texture>());
- return false;
- }
-
- current_surface_->Consume(mailbox_name, surface_rect.size());
- released_front_lock_ = NULL;
- UpdateExternalTexture();
-
- return true;
-}
-
-void RenderWidgetHostViewAura::SwapBuffersCompleted(
- const BufferPresentedCallback& ack_callback,
- const scoped_refptr<ui::Texture>& texture_to_return) {
- ui::Compositor* compositor = GetCompositor();
-
- if (frame_subscriber() && current_surface_.get() != NULL) {
- const base::Time present_time = base::Time::Now();
- scoped_refptr<media::VideoFrame> frame;
- RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
- if (frame_subscriber()->ShouldCaptureFrame(present_time,
- &frame, &callback)) {
- CopyFromCompositingSurfaceToVideoFrame(
- gfx::Rect(ConvertSizeToDIP(current_surface_->device_scale_factor(),
- current_surface_->size())),
- frame,
- base::Bind(callback, present_time));
- }
- }
-
- if (!compositor) {
- ack_callback.Run(false, texture_to_return);
- } else {
- AddOnCommitCallbackAndDisableLocks(
- base::Bind(ack_callback, false, texture_to_return));
- }
-}
-
-#if defined(OS_WIN)
-void RenderWidgetHostViewAura::UpdateTransientRects(
- const std::vector<gfx::Rect>& rects) {
- transient_rects_ = rects;
- UpdateCutoutRects();
-}
-
-void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
- const std::vector<gfx::Rect>& rects) {
- constrained_rects_ = rects;
- UpdateCutoutRects();
-}
-
-void RenderWidgetHostViewAura::UpdateCutoutRects() {
- if (!window_->GetRootWindow())
- return;
- HWND parent = window_->GetRootWindow()->GetAcceleratedWidget();
- CutoutRectsParams params;
- params.widget = this;
- params.cutout_rects.assign(transient_rects_.begin(), transient_rects_.end());
- params.cutout_rects.insert(params.cutout_rects.end(),
- constrained_rects_.begin(),
- constrained_rects_.end());
- params.geometry = &plugin_window_moves_;
- LPARAM lparam = reinterpret_cast<LPARAM>(&params);
- EnumChildWindows(parent, SetCutoutRectsCallback, lparam);
-}
-#endif
-
-void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
- int gpu_host_id) {
- BufferPresentedCallback ack_callback = base::Bind(
- &AcknowledgeBufferForGpu,
- params_in_pixel.route_id,
- gpu_host_id,
- params_in_pixel.mailbox_name);
- BuffersSwapped(params_in_pixel.size,
- gfx::Rect(params_in_pixel.size),
- params_in_pixel.scale_factor,
- params_in_pixel.mailbox_name,
- params_in_pixel.latency_info,
- ack_callback);
-}
-
-void RenderWidgetHostViewAura::SwapDelegatedFrame(
- uint32 output_surface_id,
- scoped_ptr<cc::DelegatedFrameData> frame_data,
- float frame_device_scale_factor,
- const ui::LatencyInfo& latency_info) {
- gfx::Size frame_size_in_dip;
- if (!frame_data->render_pass_list.empty()) {
- frame_size_in_dip = gfx::ToFlooredSize(gfx::ScaleSize(
- frame_data->render_pass_list.back()->output_rect.size(),
- 1.f/frame_device_scale_factor));
- }
- if (ShouldSkipFrame(frame_size_in_dip)) {
- cc::CompositorFrameAck ack;
- ack.resources.swap(frame_data->resource_list);
- RenderWidgetHostImpl::SendSwapCompositorFrameAck(
- host_->GetRoutingID(), output_surface_id,
- host_->GetProcess()->GetID(), ack);
- return;
- }
- window_->layer()->SetDelegatedFrame(frame_data.Pass(), frame_size_in_dip);
- released_front_lock_ = NULL;
- current_frame_size_ = frame_size_in_dip;
- CheckResizeLock();
-
- if (paint_observer_)
- paint_observer_->OnUpdateCompositorContent();
-
- ui::Compositor* compositor = GetCompositor();
- if (!compositor) {
- SendDelegatedFrameAck(output_surface_id);
- } else {
- compositor->SetLatencyInfo(latency_info);
- AddOnCommitCallbackAndDisableLocks(
- base::Bind(&RenderWidgetHostViewAura::SendDelegatedFrameAck,
- AsWeakPtr(),
- output_surface_id));
- }
-}
-
-void RenderWidgetHostViewAura::SendDelegatedFrameAck(uint32 output_surface_id) {
- cc::CompositorFrameAck ack;
- window_->layer()->TakeUnusedResourcesForChildCompositor(&ack.resources);
- RenderWidgetHostImpl::SendSwapCompositorFrameAck(
- host_->GetRoutingID(), output_surface_id,
- host_->GetProcess()->GetID(), ack);
-}
-
-void RenderWidgetHostViewAura::SwapSoftwareFrame(
- uint32 output_surface_id,
- scoped_ptr<cc::SoftwareFrameData> frame_data,
- float frame_device_scale_factor,
- const ui::LatencyInfo& latency_info) {
- const gfx::Size& frame_size = frame_data->size;
- const gfx::Rect& damage_rect = frame_data->damage_rect;
- gfx::Size frame_size_in_dip =
- ConvertSizeToDIP(frame_device_scale_factor, frame_size);
- if (ShouldSkipFrame(frame_size_in_dip)) {
- SendSoftwareFrameAck(output_surface_id, frame_data->id);
- return;
- }
-
- const size_t size_in_bytes = 4 * frame_size.GetArea();
-#ifdef OS_WIN
- scoped_ptr<base::SharedMemory> shared_memory(
- new base::SharedMemory(frame_data->handle, true,
- host_->GetProcess()->GetHandle()));
-#else
- scoped_ptr<base::SharedMemory> shared_memory(
- new base::SharedMemory(frame_data->handle, true));
-#endif
-
- if (!shared_memory->Map(size_in_bytes)) {
- host_->GetProcess()->ReceivedBadMessage();
- return;
- }
-
- if (last_swapped_surface_size_ != frame_size) {
- DLOG_IF(ERROR, damage_rect != gfx::Rect(frame_size))
- << "Expected full damage rect";
- }
- last_swapped_surface_size_ = frame_size;
- last_swapped_surface_scale_factor_ = frame_device_scale_factor;
-
- base::SharedMemory* shared_memory_raw_ptr = shared_memory.get();
- cc::TextureMailbox::ReleaseCallback callback =
- base::Bind(ReleaseMailbox, Passed(&shared_memory),
- base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck,
- AsWeakPtr(), output_surface_id, frame_data->id));
- current_software_frame_ =
- cc::TextureMailbox(shared_memory_raw_ptr, frame_size, callback);
- DCHECK(current_software_frame_.IsSharedMemory());
- current_frame_size_ = frame_size_in_dip;
-
- released_front_lock_ = NULL;
- CheckResizeLock();
- window_->layer()->SetTextureMailbox(current_software_frame_,
- frame_device_scale_factor);
- window_->SchedulePaintInRect(
- ConvertRectToDIP(frame_device_scale_factor, damage_rect));
-
- ui::Compositor* compositor = GetCompositor();
- if (compositor)
- compositor->SetLatencyInfo(latency_info);
- if (paint_observer_)
- paint_observer_->OnUpdateCompositorContent();
-}
-
-void RenderWidgetHostViewAura::SendSoftwareFrameAck(
- uint32 output_surface_id, unsigned software_frame_id) {
- cc::CompositorFrameAck ack;
- ack.last_software_frame_id = software_frame_id;
- RenderWidgetHostImpl::SendSwapCompositorFrameAck(
- host_->GetRoutingID(), output_surface_id,
- host_->GetProcess()->GetID(), ack);
-}
-
-void RenderWidgetHostViewAura::OnSwapCompositorFrame(
- uint32 output_surface_id,
- scoped_ptr<cc::CompositorFrame> frame) {
- if (frame->delegated_frame_data) {
- SwapDelegatedFrame(output_surface_id,
- frame->delegated_frame_data.Pass(),
- frame->metadata.device_scale_factor,
- frame->metadata.latency_info);
- return;
- }
-
- if (frame->software_frame_data) {
- SwapSoftwareFrame(output_surface_id,
- frame->software_frame_data.Pass(),
- frame->metadata.device_scale_factor,
- frame->metadata.latency_info);
- return;
- }
-
- if (!frame->gl_frame_data || frame->gl_frame_data->mailbox.IsZero())
- return;
-
- BufferPresentedCallback ack_callback = base::Bind(
- &SendCompositorFrameAck,
- host_->GetRoutingID(), output_surface_id, host_->GetProcess()->GetID(),
- frame->gl_frame_data->mailbox, frame->gl_frame_data->size);
-
- if (!frame->gl_frame_data->sync_point) {
- LOG(ERROR) << "CompositorFrame without sync point. Skipping frame...";
- ack_callback.Run(true, scoped_refptr<ui::Texture>());
- return;
- }
-
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- factory->WaitSyncPoint(frame->gl_frame_data->sync_point);
-
- std::string mailbox_name(
- reinterpret_cast<const char*>(frame->gl_frame_data->mailbox.name),
- sizeof(frame->gl_frame_data->mailbox.name));
- BuffersSwapped(frame->gl_frame_data->size,
- frame->gl_frame_data->sub_buffer_rect,
- frame->metadata.device_scale_factor,
- mailbox_name,
- frame->metadata.latency_info,
- ack_callback);
-}
-
-#if defined(OS_WIN)
-void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) {
- if (GetBrowserAccessibilityManager()) {
- GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerWin()
- ->set_parent_iaccessible(accessible_parent);
- }
-}
-#endif
-
-void RenderWidgetHostViewAura::BuffersSwapped(
- const gfx::Size& surface_size,
- const gfx::Rect& damage_rect,
- float surface_scale_factor,
- const std::string& mailbox_name,
- const ui::LatencyInfo& latency_info,
- const BufferPresentedCallback& ack_callback) {
- scoped_refptr<ui::Texture> previous_texture(current_surface_);
- const gfx::Rect surface_rect = gfx::Rect(surface_size);
-
- if (!SwapBuffersPrepare(surface_rect,
- surface_scale_factor,
- damage_rect,
- mailbox_name,
- ack_callback)) {
- return;
- }
-
- SkRegion damage(RectToSkIRect(damage_rect));
- if (!skipped_damage_.isEmpty()) {
- damage.op(skipped_damage_, SkRegion::kUnion_Op);
- skipped_damage_.setEmpty();
- }
-
- DCHECK(surface_rect.Contains(SkIRectToRect(damage.getBounds())));
- ui::Texture* current_texture = current_surface_.get();
-
- const gfx::Size surface_size_in_pixel = surface_size;
- DLOG_IF(ERROR, previous_texture.get() &&
- previous_texture->size() != current_texture->size() &&
- SkIRectToRect(damage.getBounds()) != surface_rect) <<
- "Expected full damage rect after size change";
- if (previous_texture.get() && !previous_damage_.isEmpty() &&
- previous_texture->size() == current_texture->size()) {
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- GLHelper* gl_helper = factory->GetGLHelper();
- gl_helper->CopySubBufferDamage(
- current_texture->PrepareTexture(),
- previous_texture->PrepareTexture(),
- damage,
- previous_damage_);
- }
- previous_damage_ = damage;
-
- ui::Compositor* compositor = GetCompositor();
- if (compositor) {
- // Co-ordinates come in OpenGL co-ordinate space.
- // We need to convert to layer space.
- gfx::Rect rect_to_paint =
- ConvertRectToDIP(surface_scale_factor,
- gfx::Rect(damage_rect.x(),
- surface_size_in_pixel.height() -
- damage_rect.y() - damage_rect.height(),
- damage_rect.width(),
- damage_rect.height()));
-
- // Damage may not have been DIP aligned, so inflate damage to compensate
- // for any round-off error.
- rect_to_paint.Inset(-1, -1);
- rect_to_paint.Intersect(window_->bounds());
-
- if (paint_observer_)
- paint_observer_->OnUpdateCompositorContent();
- window_->SchedulePaintInRect(rect_to_paint);
- compositor->SetLatencyInfo(latency_info);
- }
-
- SwapBuffersCompleted(ack_callback, previous_texture);
-}
-
-void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel,
- int gpu_host_id) {
- gfx::Rect damage_rect(params_in_pixel.x,
- params_in_pixel.y,
- params_in_pixel.width,
- params_in_pixel.height);
- BufferPresentedCallback ack_callback =
- base::Bind(&AcknowledgeBufferForGpu,
- params_in_pixel.route_id,
- gpu_host_id,
- params_in_pixel.mailbox_name);
- BuffersSwapped(params_in_pixel.surface_size,
- damage_rect,
- params_in_pixel.surface_scale_factor,
- params_in_pixel.mailbox_name,
- params_in_pixel.latency_info,
- ack_callback);
-}
-
-void RenderWidgetHostViewAura::AcceleratedSurfaceSuspend() {
-}
-
-void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() {
- // This really tells us to release the frontbuffer.
- if (current_surface_.get()) {
- ui::Compositor* compositor = GetCompositor();
- if (compositor) {
- // We need to wait for a commit to clear to guarantee that all we
- // will not issue any more GL referencing the previous surface.
- AddOnCommitCallbackAndDisableLocks(
- base::Bind(&RenderWidgetHostViewAura::
- SetSurfaceNotInUseByCompositor,
- AsWeakPtr(),
- current_surface_)); // Hold a ref so the texture will not
- // get deleted until after commit.
- }
- current_surface_ = NULL;
- UpdateExternalTexture();
- }
-}
-
-bool RenderWidgetHostViewAura::HasAcceleratedSurface(
- const gfx::Size& desired_size) {
- // Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
- // matter what is returned here as GetBackingStore is the only caller of this
- // method. TODO(jbates) implement this if other Aura code needs it.
- return false;
-}
-
-void RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor(
- scoped_refptr<ui::Texture>) {
-}
-
-// static
-void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult(
- const gfx::Size& dst_size_in_pixel,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- scoped_ptr<cc::CopyOutputResult> result) {
- if (result->IsEmpty() || result->size().IsEmpty()) {
- callback.Run(false, SkBitmap());
- return;
- }
-
- if (result->HasTexture()) {
- PrepareTextureCopyOutputResult(dst_size_in_pixel, callback, result.Pass());
- return;
- }
-
- DCHECK(result->HasBitmap());
- PrepareBitmapCopyOutputResult(dst_size_in_pixel, callback, result.Pass());
-}
-
-static void CopyFromCompositingSurfaceFinished(
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- const cc::TextureMailbox::ReleaseCallback& release_callback,
- scoped_ptr<SkBitmap> bitmap,
- scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
- bool result) {
- bitmap_pixels_lock.reset();
- release_callback.Run(0, false);
- callback.Run(result, *bitmap);
-}
-
-// static
-void RenderWidgetHostViewAura::PrepareTextureCopyOutputResult(
- const gfx::Size& dst_size_in_pixel,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- scoped_ptr<cc::CopyOutputResult> result) {
- base::ScopedClosureRunner scoped_callback_runner(
- base::Bind(callback, false, SkBitmap()));
-
- DCHECK(result->HasTexture());
- if (!result->HasTexture())
- return;
-
- scoped_ptr<SkBitmap> bitmap(new SkBitmap);
- bitmap->setConfig(SkBitmap::kARGB_8888_Config,
- dst_size_in_pixel.width(), dst_size_in_pixel.height());
- if (!bitmap->allocPixels())
- return;
- bitmap->setIsOpaque(true);
-
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- GLHelper* gl_helper = factory->GetGLHelper();
- if (!gl_helper)
- return;
-
- scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
- new SkAutoLockPixels(*bitmap));
- uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
-
- scoped_ptr<cc::TextureMailbox> texture_mailbox = result->TakeTexture();
- DCHECK(texture_mailbox->IsTexture());
- if (!texture_mailbox->IsTexture())
- return;
-
- scoped_callback_runner.Release();
-
- gl_helper->CropScaleReadbackAndCleanMailbox(
- texture_mailbox->name(),
- texture_mailbox->sync_point(),
- result->size(),
- gfx::Rect(result->size()),
- dst_size_in_pixel,
- pixels,
- base::Bind(&CopyFromCompositingSurfaceFinished,
- callback,
- texture_mailbox->callback(),
- base::Passed(&bitmap),
- base::Passed(&bitmap_pixels_lock)));
-}
-
-// static
-void RenderWidgetHostViewAura::PrepareBitmapCopyOutputResult(
- const gfx::Size& dst_size_in_pixel,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- scoped_ptr<cc::CopyOutputResult> result) {
- DCHECK(result->HasBitmap());
-
- base::ScopedClosureRunner scoped_callback_runner(
- base::Bind(callback, false, SkBitmap()));
- if (!result->HasBitmap())
- return;
-
- scoped_ptr<SkBitmap> source = result->TakeBitmap();
- DCHECK(source);
- if (!source)
- return;
-
- scoped_callback_runner.Release();
-
- SkBitmap bitmap = skia::ImageOperations::Resize(
- *source,
- skia::ImageOperations::RESIZE_BEST,
- dst_size_in_pixel.width(),
- dst_size_in_pixel.height());
- callback.Run(true, bitmap);
-}
-
-static void CopyFromCompositingSurfaceFinishedForVideo(
- const base::Callback<void(bool)>& callback,
- const cc::TextureMailbox::ReleaseCallback& release_callback,
- bool result) {
- release_callback.Run(0, false);
- callback.Run(result);
-}
-
-// static
-void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo(
- base::WeakPtr<RenderWidgetHostViewAura> rwhva,
- scoped_refptr<media::VideoFrame> video_frame,
- const base::Callback<void(bool)>& callback,
- scoped_ptr<cc::CopyOutputResult> result) {
- base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
-
- if (!rwhva)
- return;
-
- if (result->IsEmpty())
- return;
- if (result->size().IsEmpty())
- return;
-
- // Compute the dest size we want after the letterboxing resize. Make the
- // coordinates and sizes even because we letterbox in YUV space
- // (see CopyRGBToVideoFrame). They need to be even for the UV samples to
- // line up correctly.
- // The video frame's coded_size() and the result's size() are both physical
- // pixels.
- gfx::Rect region_in_frame =
- media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()),
- result->size());
- region_in_frame = gfx::Rect(region_in_frame.x() & ~1,
- region_in_frame.y() & ~1,
- region_in_frame.width() & ~1,
- region_in_frame.height() & ~1);
- if (region_in_frame.IsEmpty())
- return;
-
- // We only handle texture readbacks for now. If the compositor is in software
- // mode, we could produce a software-backed VideoFrame here as well.
- if (!result->HasTexture())
- return;
-
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- GLHelper* gl_helper = factory->GetGLHelper();
- if (!gl_helper)
- return;
-
- scoped_ptr<cc::TextureMailbox> texture_mailbox = result->TakeTexture();
- DCHECK(texture_mailbox->IsTexture());
- if (!texture_mailbox->IsTexture())
- return;
-
- gfx::Rect result_rect(result->size());
-
- content::ReadbackYUVInterface* yuv_readback_pipeline =
- rwhva->yuv_readback_pipeline_.get();
- if (yuv_readback_pipeline == NULL ||
- yuv_readback_pipeline->scaler()->SrcSize() != result_rect.size() ||
- yuv_readback_pipeline->scaler()->SrcSubrect() != result_rect ||
- yuv_readback_pipeline->scaler()->DstSize() != region_in_frame.size()) {
- GLHelper::ScalerQuality quality = GLHelper::SCALER_QUALITY_FAST;
- std::string quality_switch = switches::kTabCaptureDownscaleQuality;
- // If we're scaling up, we can use the "best" quality.
- if (result_rect.size().width() < region_in_frame.size().width() &&
- result_rect.size().height() < region_in_frame.size().height())
- quality_switch = switches::kTabCaptureUpscaleQuality;
-
- std::string switch_value =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(quality_switch);
- if (switch_value == "fast")
- quality = GLHelper::SCALER_QUALITY_FAST;
- else if (switch_value == "good")
- quality = GLHelper::SCALER_QUALITY_GOOD;
- else if (switch_value == "best")
- quality = GLHelper::SCALER_QUALITY_BEST;
-
- rwhva->yuv_readback_pipeline_.reset(
- gl_helper->CreateReadbackPipelineYUV(quality,
- result_rect.size(),
- result_rect,
- video_frame->coded_size(),
- region_in_frame,
- true,
- false));
- yuv_readback_pipeline = rwhva->yuv_readback_pipeline_.get();
- }
-
- scoped_callback_runner.Release();
- base::Callback<void(bool result)> finished_callback = base::Bind(
- &CopyFromCompositingSurfaceFinishedForVideo,
- callback,
- texture_mailbox->callback());
- yuv_readback_pipeline->ReadbackYUV(
- texture_mailbox->name(),
- texture_mailbox->sync_point(),
- video_frame.get(),
- finished_callback);
-}
-
-void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) {
- GetScreenInfoForWindow(results, window_->GetRootWindow() ? window_ : NULL);
-}
-
-gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
- return window_->GetToplevelWindow()->GetBoundsInScreen();
-}
-
-void RenderWidgetHostViewAura::GestureEventAck(int gesture_event_type) {
- if (touch_editing_client_)
- touch_editing_client_->GestureEventAck(gesture_event_type);
-}
-
-void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
- const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
- ScopedVector<ui::TouchEvent> events;
- if (!MakeUITouchEventsFromWebTouchEvents(touch, &events,
- SCREEN_COORDINATES))
- return;
-
- aura::RootWindow* root = window_->GetRootWindow();
- // |root| is NULL during tests.
- if (!root)
- return;
-
- ui::EventResult result = (ack_result ==
- INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
- for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
- end = events.end(); iter != end; ++iter) {
- root->ProcessedTouchEvent((*iter), window_, result);
- }
-}
-
-SmoothScrollGesture* RenderWidgetHostViewAura::CreateSmoothScrollGesture(
- bool scroll_down,
- int pixels_to_scroll,
- int mouse_event_x,
- int mouse_event_y) {
- return new TouchSmoothScrollGestureAura(scroll_down,
- pixels_to_scroll,
- mouse_event_x,
- mouse_event_y,
- window_);
-}
-
-void RenderWidgetHostViewAura::SetHasHorizontalScrollbar(
- bool has_horizontal_scrollbar) {
- // Not needed. Mac-only.
-}
-
-void RenderWidgetHostViewAura::SetScrollOffsetPinning(
- bool is_pinned_to_left, bool is_pinned_to_right) {
- // Not needed. Mac-only.
-}
-
-void RenderWidgetHostViewAura::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
- BrowserAccessibilityManager* manager =
- GetOrCreateBrowserAccessibilityManager();
- if (manager)
- manager->OnAccessibilityNotifications(params);
-}
-
-gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
- if (shared_surface_handle_.is_null()) {
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- shared_surface_handle_ = factory->CreateSharedSurfaceHandle();
- factory->AddObserver(this);
- }
- return shared_surface_handle_;
-}
-
-bool RenderWidgetHostViewAura::LockMouse() {
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (!root_window)
- return false;
-
- if (mouse_locked_)
- return true;
-
- mouse_locked_ = true;
- window_->SetCapture();
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(root_window);
- if (cursor_client) {
- cursor_client->HideCursor();
- cursor_client->LockCursor();
- }
-
- if (ShouldMoveToCenter()) {
- synthetic_move_sent_ = true;
- window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
- }
- if (aura::client::GetTooltipClient(root_window))
- aura::client::GetTooltipClient(root_window)->SetTooltipsEnabled(false);
- return true;
-}
-
-void RenderWidgetHostViewAura::UnlockMouse() {
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (!mouse_locked_ || !root_window)
- return;
-
- mouse_locked_ = false;
-
- window_->ReleaseCapture();
- window_->MoveCursorTo(unlocked_mouse_position_);
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(root_window);
- if (cursor_client) {
- cursor_client->UnlockCursor();
- cursor_client->ShowCursor();
- }
-
- if (aura::client::GetTooltipClient(root_window))
- aura::client::GetTooltipClient(root_window)->SetTooltipsEnabled(true);
-
- host_->LostMouseLock();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, ui::TextInputClient implementation:
-void RenderWidgetHostViewAura::SetCompositionText(
- const ui::CompositionText& composition) {
- if (!host_)
- return;
-
- // ui::CompositionUnderline should be identical to
- // WebKit::WebCompositionUnderline, so that we can do reinterpret_cast safely.
- COMPILE_ASSERT(sizeof(ui::CompositionUnderline) ==
- sizeof(WebKit::WebCompositionUnderline),
- ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
-
- // TODO(suzhe): convert both renderer_host and renderer to use
- // ui::CompositionText.
- const std::vector<WebKit::WebCompositionUnderline>& underlines =
- reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>(
- composition.underlines);
-
- // TODO(suzhe): due to a bug of webkit, we can't use selection range with
- // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
- host_->ImeSetComposition(composition.text, underlines,
- composition.selection.end(),
- composition.selection.end());
-
- has_composition_text_ = !composition.text.empty();
-}
-
-void RenderWidgetHostViewAura::ConfirmCompositionText() {
- if (host_ && has_composition_text_)
- host_->ImeConfirmComposition(string16(), ui::Range::InvalidRange(), false);
- has_composition_text_ = false;
-}
-
-void RenderWidgetHostViewAura::ClearCompositionText() {
- if (host_ && has_composition_text_)
- host_->ImeCancelComposition();
- has_composition_text_ = false;
-}
-
-void RenderWidgetHostViewAura::InsertText(const string16& text) {
- DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
- if (host_)
- host_->ImeConfirmComposition(text, ui::Range::InvalidRange(), false);
- has_composition_text_ = false;
-}
-
-void RenderWidgetHostViewAura::InsertChar(char16 ch, int flags) {
- if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
- popup_child_host_view_->InsertChar(ch, flags);
- return;
- }
-
- if (host_) {
- double now = ui::EventTimeForNow().InSecondsF();
- // Send a WebKit::WebInputEvent::Char event to |host_|.
- NativeWebKeyboardEvent webkit_event(ui::ET_KEY_PRESSED,
- true /* is_char */,
- ch,
- flags,
- now);
- host_->ForwardKeyboardEvent(webkit_event);
- }
-}
-
-gfx::NativeWindow RenderWidgetHostViewAura::GetAttachedWindow() const {
- return window_;
-}
-
-ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const {
- return text_input_type_;
-}
-
-bool RenderWidgetHostViewAura::CanComposeInline() const {
- return can_compose_inline_;
-}
-
-gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(const gfx::Rect& rect) {
- gfx::Point origin = rect.origin();
- gfx::Point end = gfx::Point(rect.right(), rect.bottom());
-
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (root_window) {
- aura::client::ScreenPositionClient* screen_position_client =
- aura::client::GetScreenPositionClient(root_window);
- screen_position_client->ConvertPointToScreen(window_, &origin);
- screen_position_client->ConvertPointToScreen(window_, &end);
- return gfx::Rect(origin.x(),
- origin.y(),
- end.x() - origin.x(),
- end.y() - origin.y());
- }
-
- return rect;
-}
-
-gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
- const gfx::Rect& rect) {
- gfx::Point origin = rect.origin();
- gfx::Point end = gfx::Point(rect.right(), rect.bottom());
-
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (root_window) {
- aura::client::ScreenPositionClient* screen_position_client =
- aura::client::GetScreenPositionClient(root_window);
- screen_position_client->ConvertPointFromScreen(window_, &origin);
- screen_position_client->ConvertPointFromScreen(window_, &end);
- return gfx::Rect(origin.x(),
- origin.y(),
- end.x() - origin.x(),
- end.y() - origin.y());
- }
-
- return rect;
-}
-
-gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() {
- const gfx::Rect rect =
- gfx::UnionRects(selection_anchor_rect_, selection_focus_rect_);
- return ConvertRectToScreen(rect);
-}
-
-bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(uint32 index,
- gfx::Rect* rect) {
- DCHECK(rect);
- if (index >= composition_character_bounds_.size())
- return false;
- *rect = ConvertRectToScreen(composition_character_bounds_[index]);
- return true;
-}
-
-bool RenderWidgetHostViewAura::HasCompositionText() {
- return has_composition_text_;
-}
-
-bool RenderWidgetHostViewAura::GetTextRange(ui::Range* range) {
- range->set_start(selection_text_offset_);
- range->set_end(selection_text_offset_ + selection_text_.length());
- return true;
-}
-
-bool RenderWidgetHostViewAura::GetCompositionTextRange(ui::Range* range) {
- // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
- NOTIMPLEMENTED();
- return false;
-}
-
-bool RenderWidgetHostViewAura::GetSelectionRange(ui::Range* range) {
- range->set_start(selection_range_.start());
- range->set_end(selection_range_.end());
- return true;
-}
-
-bool RenderWidgetHostViewAura::SetSelectionRange(const ui::Range& range) {
- // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
- NOTIMPLEMENTED();
- return false;
-}
-
-bool RenderWidgetHostViewAura::DeleteRange(const ui::Range& range) {
- // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
- NOTIMPLEMENTED();
- return false;
-}
-
-bool RenderWidgetHostViewAura::GetTextFromRange(
- const ui::Range& range,
- string16* text) {
- ui::Range selection_text_range(selection_text_offset_,
- selection_text_offset_ + selection_text_.length());
-
- if (!selection_text_range.Contains(range)) {
- text->clear();
- return false;
- }
- if (selection_text_range.EqualsIgnoringDirection(range)) {
- // Avoid calling substr whose performance is low.
- *text = selection_text_;
- } else {
- *text = selection_text_.substr(
- range.GetMin() - selection_text_offset_,
- range.length());
- }
- return true;
-}
-
-void RenderWidgetHostViewAura::OnInputMethodChanged() {
- if (!host_)
- return;
-
- if (GetInputMethod())
- host_->SetInputMethodActive(GetInputMethod()->IsActive());
-
- // TODO(suzhe): implement the newly added “locale” property of HTML DOM
- // TextEvent.
-}
-
-bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
- base::i18n::TextDirection direction) {
- if (!host_)
- return false;
- host_->UpdateTextDirection(
- direction == base::i18n::RIGHT_TO_LEFT ?
- WebKit::WebTextDirectionRightToLeft :
- WebKit::WebTextDirectionLeftToRight);
- host_->NotifyTextDirection();
- return true;
-}
-
-void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
- size_t before, size_t after) {
- if (host_)
- host_->ExtendSelectionAndDelete(before, after);
-}
-
-void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
- gfx::Rect intersected_rect(
- gfx::IntersectRects(rect, window_->GetBoundsInScreen()));
-
- if (intersected_rect.IsEmpty())
- return;
-
- host_->ScrollFocusedEditableNodeIntoRect(
- ConvertRectFromScreen(intersected_rect));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, gfx::DisplayObserver implementation:
-
-void RenderWidgetHostViewAura::OnDisplayBoundsChanged(
- const gfx::Display& display) {
- gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
- if (display.id() == screen->GetDisplayNearestWindow(window_).id()) {
- UpdateScreenInfo(window_);
- }
-}
-
-void RenderWidgetHostViewAura::OnDisplayAdded(
- const gfx::Display& new_display) {
-}
-
-void RenderWidgetHostViewAura::OnDisplayRemoved(
- const gfx::Display& old_display) {
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, aura::WindowDelegate implementation:
-
-gfx::Size RenderWidgetHostViewAura::GetMinimumSize() const {
- return gfx::Size();
-}
-
-gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const {
- return gfx::Size();
-}
-
-void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) {
- // We care about this only in fullscreen mode, where there is no
- // WebContentsViewAura. We are sized via SetSize() or SetBounds() by
- // WebContentsViewAura in other cases.
- if (is_fullscreen_)
- SetSize(new_bounds.size());
-}
-
-gfx::NativeCursor RenderWidgetHostViewAura::GetCursor(const gfx::Point& point) {
- if (mouse_locked_)
- return ui::kCursorNone;
- return current_cursor_.GetNativeCursor();
-}
-
-int RenderWidgetHostViewAura::GetNonClientComponent(
- const gfx::Point& point) const {
- return HTCLIENT;
-}
-
-bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
- aura::Window* child,
- const gfx::Point& location) {
- return true;
-}
-
-bool RenderWidgetHostViewAura::CanFocus() {
- return popup_type_ == WebKit::WebPopupTypeNone;
-}
-
-void RenderWidgetHostViewAura::OnCaptureLost() {
- host_->LostCapture();
- if (touch_editing_client_)
- touch_editing_client_->EndTouchEditing();
-}
-
-void RenderWidgetHostViewAura::OnPaint(gfx::Canvas* canvas) {
- bool has_backing_store = !!host_->GetBackingStore(false);
- if (has_backing_store) {
- paint_canvas_ = canvas;
- BackingStoreAura* backing_store = static_cast<BackingStoreAura*>(
- host_->GetBackingStore(true));
- paint_canvas_ = NULL;
- backing_store->SkiaShowRect(gfx::Point(), canvas);
-
- if (paint_observer_)
- paint_observer_->OnPaintComplete();
- ui::Compositor* compositor = GetCompositor();
- if (compositor) {
- compositor->SetLatencyInfo(software_latency_info_);
- software_latency_info_.Clear();
- }
- } else {
- // For non-opaque windows, we don't draw anything, since we depend on the
- // canvas coming from the compositor to already be initialized as
- // transparent.
- if (window_->layer()->fills_bounds_opaquely())
- canvas->DrawColor(SK_ColorWHITE);
- }
-}
-
-void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
- float device_scale_factor) {
- if (!host_)
- return;
-
- BackingStoreAura* backing_store = static_cast<BackingStoreAura*>(
- host_->GetBackingStore(false));
- if (backing_store) // NULL in hardware path.
- backing_store->ScaleFactorChanged(device_scale_factor);
-
- UpdateScreenInfo(window_);
- DCHECK_EQ(current_device_scale_factor_, device_scale_factor);
- current_cursor_.SetDeviceScaleFactor(device_scale_factor);
-}
-
-void RenderWidgetHostViewAura::OnWindowDestroying() {
-#if defined(OS_WIN)
- HWND parent = NULL;
- // If the tab was hidden and it's closed, host_->is_hidden would have been
- // reset to false in RenderWidgetHostImpl::RendererExited.
- if (!window_->GetRootWindow() || host_->is_hidden()) {
- parent = ui::GetHiddenWindow();
- } else {
- parent = window_->GetRootWindow()->GetAcceleratedWidget();
- }
- LPARAM lparam = reinterpret_cast<LPARAM>(this);
- EnumChildWindows(parent, WindowDestroyingCallback, lparam);
-#endif
-}
-
-void RenderWidgetHostViewAura::OnWindowDestroyed() {
- host_->ViewDestroyed();
- delete this;
-}
-
-void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible) {
-}
-
-bool RenderWidgetHostViewAura::HasHitTestMask() const {
- return false;
-}
-
-void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
-}
-
-scoped_refptr<ui::Texture> RenderWidgetHostViewAura::CopyTexture() {
- if (!host_->is_accelerated_compositing_active())
- return scoped_refptr<ui::Texture>();
-
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- GLHelper* gl_helper = factory->GetGLHelper();
- if (!gl_helper)
- return scoped_refptr<ui::Texture>();
-
- if (!current_surface_.get())
- return scoped_refptr<ui::Texture>();
-
- WebKit::WebGLId texture_id =
- gl_helper->CopyTexture(current_surface_->PrepareTexture(),
- current_surface_->size());
- if (!texture_id)
- return scoped_refptr<ui::Texture>();
-
- return scoped_refptr<ui::Texture>(
- factory->CreateOwnedTexture(
- current_surface_->size(),
- current_surface_->device_scale_factor(), texture_id));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, ui::EventHandler implementation:
-
-void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
- TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent");
- if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
- return;
-
- if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
- popup_child_host_view_->OnKeyEvent(event);
- if (event->handled())
- return;
- }
-
- // We need to handle the Escape key for Pepper Flash.
- if (is_fullscreen_ && event->key_code() == ui::VKEY_ESCAPE) {
- // Focus the window we were created from.
- if (host_tracker_.get() && !host_tracker_->windows().empty()) {
- aura::Window* host = *(host_tracker_->windows().begin());
- aura::client::FocusClient* client = aura::client::GetFocusClient(host);
- if (client) {
- // Calling host->Focus() may delete |this|. We create a local
- // observer for that. In that case we exit without further
- // access to any members.
- aura::WindowDestructionObserver destruction_observer(window_);
- host->Focus();
- if (destruction_observer.destroyed()) {
- event->SetHandled();
- return;
- }
- }
- }
- if (!in_shutdown_) {
- in_shutdown_ = true;
- host_->Shutdown();
- }
- } else {
- // We don't have to communicate with an input method here.
- if (!event->HasNativeEvent()) {
- NativeWebKeyboardEvent webkit_event(
- event->type(),
- event->is_char(),
- event->is_char() ? event->GetCharacter() : event->key_code(),
- event->flags(),
- ui::EventTimeForNow().InSecondsF());
- host_->ForwardKeyboardEvent(webkit_event);
- } else {
- NativeWebKeyboardEvent webkit_event(event);
- host_->ForwardKeyboardEvent(webkit_event);
- }
- }
- event->SetHandled();
-}
-
-void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
- TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
-
- if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
- return;
-
- if (mouse_locked_) {
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(window_->GetRootWindow());
- DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
-
- if (event->type() == ui::ET_MOUSEWHEEL) {
- WebKit::WebMouseWheelEvent mouse_wheel_event =
- MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
- if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
- host_->ForwardWheelEvent(mouse_wheel_event);
- return;
- }
-
- WebKit::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
- gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
-
- bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED ||
- event->type() == ui::ET_MOUSE_DRAGGED) &&
- mouse_event.x == center.x() && mouse_event.y == center.y();
-
- ModifyEventMovementAndCoords(&mouse_event);
-
- bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
- if (should_not_forward) {
- synthetic_move_sent_ = false;
- } else {
- // Check if the mouse has reached the border and needs to be centered.
- if (ShouldMoveToCenter()) {
- synthetic_move_sent_ = true;
- window_->MoveCursorTo(center);
- }
- // Forward event to renderer.
- if (CanRendererHandleEvent(event) &&
- !(event->flags() & ui::EF_FROM_TOUCH))
- host_->ForwardMouseEvent(mouse_event);
- }
- return;
- }
-
- // As the overscroll is handled during scroll events from the trackpad, the
- // RWHVA window is transformed by the overscroll controller. This transform
- // triggers a synthetic mouse-move event to be generated (by the aura
- // RootWindow). But this event interferes with the overscroll gesture. So,
- // ignore such synthetic mouse-move events if an overscroll gesture is in
- // progress.
- if (host_->overscroll_controller() &&
- host_->overscroll_controller()->overscroll_mode() != OVERSCROLL_NONE &&
- event->flags() & ui::EF_IS_SYNTHESIZED &&
- (event->type() == ui::ET_MOUSE_ENTERED ||
- event->type() == ui::ET_MOUSE_EXITED ||
- event->type() == ui::ET_MOUSE_MOVED)) {
- event->StopPropagation();
- return;
- }
-
- if (event->type() == ui::ET_MOUSEWHEEL) {
-#if defined(OS_WIN)
- // We get mouse wheel/scroll messages even if we are not in the foreground.
- // So here we check if we have any owned popup windows in the foreground and
- // dismiss them.
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (root_window) {
- HWND parent = root_window->GetAcceleratedWidget();
- HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
- EnumThreadWindows(GetCurrentThreadId(),
- DismissOwnedPopups,
- reinterpret_cast<LPARAM>(toplevel_hwnd));
- }
-#endif
- WebKit::WebMouseWheelEvent mouse_wheel_event =
- MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
- if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
- host_->ForwardWheelEvent(mouse_wheel_event);
- } else if (CanRendererHandleEvent(event) &&
- !(event->flags() & ui::EF_FROM_TOUCH)) {
- WebKit::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
- ModifyEventMovementAndCoords(&mouse_event);
- host_->ForwardMouseEvent(mouse_event);
- }
-
- switch (event->type()) {
- case ui::ET_MOUSE_PRESSED:
- window_->SetCapture();
- // Confirm existing composition text on mouse click events, to make sure
- // the input caret won't be moved with an ongoing composition text.
- FinishImeCompositionSession();
- break;
- case ui::ET_MOUSE_RELEASED:
- window_->ReleaseCapture();
- break;
- default:
- break;
- }
-
- // Needed to propagate mouse event to native_tab_contents_view_aura.
- // TODO(pkotwicz): Find a better way of doing this.
- // In fullscreen mode which is typically used by flash, don't forward
- // the mouse events to the parent. The renderer and the plugin process
- // handle these events.
- if (!is_fullscreen_ && window_->parent()->delegate() &&
- !(event->flags() & ui::EF_FROM_TOUCH))
- window_->parent()->delegate()->OnMouseEvent(event);
-
- if (!IsXButtonUpEvent(event))
- event->SetHandled();
-}
-
-void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
- TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
- if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
- return;
-
- if (event->type() == ui::ET_SCROLL) {
- if (event->finger_count() != 2)
- return;
- WebKit::WebGestureEvent gesture_event =
- MakeWebGestureEventFlingCancel();
- host_->ForwardGestureEvent(gesture_event);
- WebKit::WebMouseWheelEvent mouse_wheel_event =
- MakeWebMouseWheelEvent(event);
- host_->ForwardWheelEvent(mouse_wheel_event);
- RecordAction(UserMetricsAction("TrackpadScroll"));
- } else if (event->type() == ui::ET_SCROLL_FLING_START ||
- event->type() == ui::ET_SCROLL_FLING_CANCEL) {
- WebKit::WebGestureEvent gesture_event =
- MakeWebGestureEvent(event);
- host_->ForwardGestureEvent(gesture_event);
- if (event->type() == ui::ET_SCROLL_FLING_START)
- RecordAction(UserMetricsAction("TrackpadScrollFling"));
- }
-
- event->SetHandled();
-}
-
-void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
- TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent");
- if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
- return;
-
- // Update the touch event first.
- WebKit::WebTouchPoint* point = UpdateWebTouchEventFromUIEvent(*event,
- &touch_event_);
-
- // Forward the touch event only if a touch point was updated, and there's a
- // touch-event handler in the page, and no other touch-event is in the queue.
- // It is important to always consume the event if there is a touch-event
- // handler in the page, or some touch-event is already in the queue, even if
- // no point has been updated, to make sure that this event does not get
- // processed by the gesture recognizer before the events in the queue.
- if (host_->ShouldForwardTouchEvent())
- event->StopPropagation();
-
- if (point) {
- if (host_->ShouldForwardTouchEvent())
- host_->ForwardTouchEventWithLatencyInfo(touch_event_, *event->latency());
- UpdateWebTouchEventAfterDispatch(&touch_event_, point);
- }
-}
-
-void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
- TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent");
- // Pinch gestures are currently disabled by default. See crbug.com/128477.
- if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN ||
- event->type() == ui::ET_GESTURE_PINCH_UPDATE ||
- event->type() == ui::ET_GESTURE_PINCH_END) && !ShouldSendPinchGesture()) {
- event->SetHandled();
- return;
- }
-
- if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
- return;
-
- RenderViewHostDelegate* delegate = NULL;
- if (popup_type_ == WebKit::WebPopupTypeNone && !is_fullscreen_)
- delegate = RenderViewHost::From(host_)->GetDelegate();
-
- if (delegate && event->type() == ui::ET_GESTURE_BEGIN &&
- event->details().touch_points() == 1) {
- delegate->HandleGestureBegin();
- }
-
- WebKit::WebGestureEvent gesture = MakeWebGestureEvent(event);
- if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
- // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
- // event to stop any in-progress flings.
- WebKit::WebGestureEvent fling_cancel = gesture;
- fling_cancel.type = WebKit::WebInputEvent::GestureFlingCancel;
- fling_cancel.sourceDevice = WebKit::WebGestureEvent::Touchscreen;
- host_->ForwardGestureEvent(fling_cancel);
- }
-
- if (gesture.type != WebKit::WebInputEvent::Undefined) {
- host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
-
- if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
- event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
- event->type() == ui::ET_GESTURE_SCROLL_END) {
- RecordAction(UserMetricsAction("TouchscreenScroll"));
- } else if (event->type() == ui::ET_SCROLL_FLING_START) {
- RecordAction(UserMetricsAction("TouchscreenScrollFling"));
- }
- }
-
- if (delegate && event->type() == ui::ET_GESTURE_END &&
- event->details().touch_points() == 1) {
- delegate->HandleGestureEnd();
- }
-
- // If a gesture is not processed by the webpage, then WebKit processes it
- // (e.g. generates synthetic mouse events).
- event->SetHandled();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation:
-
-bool RenderWidgetHostViewAura::ShouldActivate() const {
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (!root_window)
- return true;
- const ui::Event* event = root_window->current_event();
- if (!event)
- return true;
- return is_fullscreen_;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura,
-// aura::client::ActivationChangeObserver implementation:
-
-void RenderWidgetHostViewAura::OnWindowActivated(aura::Window* gained_active,
- aura::Window* lost_active) {
- DCHECK(window_ == gained_active || window_ == lost_active);
- if (window_ == gained_active) {
- const ui::Event* event = window_->GetRootWindow()->current_event();
- if (event && PointerEventActivates(*event))
- host_->OnPointerEventActivate();
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation:
-
-void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible) {
- NotifyRendererOfCursorVisibilityState(is_visible);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation:
-
-void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
- aura::Window* lost_focus) {
- DCHECK(window_ == gained_focus || window_ == lost_focus);
- if (window_ == gained_focus) {
- // We need to honor input bypass if the associated tab is does not want
- // input. This gives the current focused window a chance to be the text
- // input client and handle events.
- if (host_->ignore_input_events())
- return;
-
- host_->GotFocus();
- host_->SetActive(true);
-
- ui::InputMethod* input_method = GetInputMethod();
- if (input_method) {
- // Ask the system-wide IME to send all TextInputClient messages to |this|
- // object.
- input_method->SetFocusedTextInputClient(this);
- host_->SetInputMethodActive(input_method->IsActive());
-
- // Often the application can set focus to the view in response to a key
- // down. However the following char event shouldn't be sent to the web
- // page.
- host_->SuppressNextCharEvents();
- } else {
- host_->SetInputMethodActive(false);
- }
- } else if (window_ == lost_focus) {
- host_->SetActive(false);
- host_->Blur();
-
- DetachFromInputMethod();
- host_->SetInputMethodActive(false);
-
- if (touch_editing_client_)
- touch_editing_client_->EndTouchEditing();
-
- // If we lose the focus while fullscreen, close the window; Pepper Flash
- // won't do it for us (unlike NPAPI Flash). However, we do not close the
- // window if we lose the focus to a window on another display.
- gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
- bool focusing_other_display =
- gained_focus && screen->GetNumDisplays() > 1 &&
- (screen->GetDisplayNearestWindow(window_).id() !=
- screen->GetDisplayNearestWindow(gained_focus).id());
- if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) {
- in_shutdown_ = true;
- host_->Shutdown();
- }
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, aura::RootWindowObserver implementation:
-
-void RenderWidgetHostViewAura::OnRootWindowHostMoved(
- const aura::RootWindow* root,
- const gfx::Point& new_origin) {
- UpdateScreenInfo(window_);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, ui::CompositorObserver implementation:
-
-void RenderWidgetHostViewAura::OnCompositingDidCommit(
- ui::Compositor* compositor) {
- if (can_lock_compositor_ == NO_PENDING_COMMIT) {
- can_lock_compositor_ = YES;
- if (resize_lock_.get() && resize_lock_->GrabDeferredLock())
- can_lock_compositor_ = YES_DID_LOCK;
- }
- RunOnCommitCallbacks();
- if (resize_lock_ && resize_lock_->expected_size() == current_frame_size_) {
- resize_lock_.reset();
- host_->WasResized();
- // We may have had a resize while we had the lock (e.g. if the lock expired,
- // or if the UI still gave us some resizes), so make sure we grab a new lock
- // if necessary.
- MaybeCreateResizeLock();
- }
-}
-
-void RenderWidgetHostViewAura::OnCompositingStarted(
- ui::Compositor* compositor, base::TimeTicks start_time) {
- last_draw_ended_ = start_time;
-}
-
-void RenderWidgetHostViewAura::OnCompositingEnded(
- ui::Compositor* compositor) {
- if (paint_observer_)
- paint_observer_->OnCompositingComplete();
-}
-
-void RenderWidgetHostViewAura::OnCompositingAborted(
- ui::Compositor* compositor) {
-}
-
-void RenderWidgetHostViewAura::OnCompositingLockStateChanged(
- ui::Compositor* compositor) {
- // A compositor lock that is part of a resize lock timed out. We
- // should display a renderer frame.
- if (!compositor->IsLocked() && can_lock_compositor_ == YES_DID_LOCK) {
- can_lock_compositor_ = NO_PENDING_RENDERER_FRAME;
- }
-}
-
-void RenderWidgetHostViewAura::OnUpdateVSyncParameters(
- ui::Compositor* compositor,
- base::TimeTicks timebase,
- base::TimeDelta interval) {
- if (IsShowing() && !last_draw_ended_.is_null())
- host_->UpdateVSyncParameters(last_draw_ended_, interval);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, BrowserAccessibilityDelegate implementation:
-
-void RenderWidgetHostViewAura::SetAccessibilityFocus(int acc_obj_id) {
- if (!host_)
- return;
-
- host_->AccessibilitySetFocus(acc_obj_id);
-}
-
-void RenderWidgetHostViewAura::AccessibilityDoDefaultAction(int acc_obj_id) {
- if (!host_)
- return;
-
- host_->AccessibilityDoDefaultAction(acc_obj_id);
-}
-
-void RenderWidgetHostViewAura::AccessibilityScrollToMakeVisible(
- int acc_obj_id, gfx::Rect subfocus) {
- if (!host_)
- return;
-
- host_->AccessibilityScrollToMakeVisible(acc_obj_id, subfocus);
-}
-
-void RenderWidgetHostViewAura::AccessibilityScrollToPoint(
- int acc_obj_id, gfx::Point point) {
- if (!host_)
- return;
-
- host_->AccessibilityScrollToPoint(acc_obj_id, point);
-}
-
-void RenderWidgetHostViewAura::AccessibilitySetTextSelection(
- int acc_obj_id, int start_offset, int end_offset) {
- if (!host_)
- return;
-
- host_->AccessibilitySetTextSelection(
- acc_obj_id, start_offset, end_offset);
-}
-
-gfx::Point RenderWidgetHostViewAura::GetLastTouchEventLocation() const {
- // Only needed for Win 8 non-aura.
- return gfx::Point();
-}
-
-void RenderWidgetHostViewAura::FatalAccessibilityTreeError() {
- host_->FatalAccessibilityTreeError();
- SetBrowserAccessibilityManager(NULL);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, ImageTransportFactoryObserver implementation:
-
-void RenderWidgetHostViewAura::OnLostResources() {
- current_surface_ = NULL;
- UpdateExternalTexture();
-
- // Make sure all ImageTransportClients are deleted now that the context those
- // are using is becoming invalid. This sends pending ACKs and needs to happen
- // after calling UpdateExternalTexture() which syncs with the impl thread.
- RunOnCommitCallbacks();
-
- DCHECK(!shared_surface_handle_.is_null());
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- factory->DestroySharedSurfaceHandle(shared_surface_handle_);
- shared_surface_handle_ = factory->CreateSharedSurfaceHandle();
- host_->CompositingSurfaceUpdated();
- host_->ScheduleComposite();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, private:
-
-RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
- if (paint_observer_)
- paint_observer_->OnViewDestroyed();
- if (touch_editing_client_)
- touch_editing_client_->OnViewDestroyed();
- if (!shared_surface_handle_.is_null()) {
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- factory->DestroySharedSurfaceHandle(shared_surface_handle_);
- factory->RemoveObserver(this);
- }
- window_observer_.reset();
-#if defined(OS_WIN)
- transient_observer_.reset();
-#endif
- if (window_->GetRootWindow())
- window_->GetRootWindow()->RemoveRootWindowObserver(this);
- UnlockMouse();
- if (popup_type_ != WebKit::WebPopupTypeNone && popup_parent_host_view_) {
- DCHECK(popup_parent_host_view_->popup_child_host_view_ == NULL ||
- popup_parent_host_view_->popup_child_host_view_ == this);
- popup_parent_host_view_->popup_child_host_view_ = NULL;
- }
- if (popup_child_host_view_) {
- DCHECK(popup_child_host_view_->popup_parent_host_view_ == NULL ||
- popup_child_host_view_->popup_parent_host_view_ == this);
- popup_child_host_view_->popup_parent_host_view_ = NULL;
- }
- aura::client::SetTooltipText(window_, NULL);
- gfx::Screen::GetScreenFor(window_)->RemoveObserver(this);
-
- // This call is usually no-op since |this| object is already removed from the
- // Aura root window and we don't have a way to get an input method object
- // associated with the window, but just in case.
- DetachFromInputMethod();
-}
-
-void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
- const gfx::Point screen_point =
- gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (!root_window)
- return;
-
- gfx::Rect screen_rect = GetViewBounds();
- gfx::Point local_point = screen_point;
- local_point.Offset(-screen_rect.x(), -screen_rect.y());
-
- if (root_window->GetEventHandlerForPoint(local_point) != window_)
- return;
-
- gfx::NativeCursor cursor = current_cursor_.GetNativeCursor();
- // Do not show loading cursor when the cursor is currently hidden.
- if (is_loading_ && cursor != ui::kCursorNone)
- cursor = ui::kCursorPointer;
-
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(root_window);
- if (cursor_client) {
- cursor_client->SetCursor(cursor);
- }
-}
-
-ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (!root_window)
- return NULL;
- return root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
-}
-
-bool RenderWidgetHostViewAura::NeedsInputGrab() {
- return popup_type_ == WebKit::WebPopupTypeSelect;
-}
-
-void RenderWidgetHostViewAura::FinishImeCompositionSession() {
- if (!has_composition_text_)
- return;
- if (host_)
- host_->ImeConfirmComposition(string16(), ui::Range::InvalidRange(), false);
- ImeCancelComposition();
-}
-
-void RenderWidgetHostViewAura::ModifyEventMovementAndCoords(
- WebKit::WebMouseEvent* event) {
- // If the mouse has just entered, we must report zero movementX/Y. Hence we
- // reset any global_mouse_position set previously.
- if (event->type == WebKit::WebInputEvent::MouseEnter ||
- event->type == WebKit::WebInputEvent::MouseLeave)
- global_mouse_position_.SetPoint(event->globalX, event->globalY);
-
- // Movement is computed by taking the difference of the new cursor position
- // and the previous. Under mouse lock the cursor will be warped back to the
- // center so that we are not limited by clipping boundaries.
- // We do not measure movement as the delta from cursor to center because
- // we may receive more mouse movement events before our warp has taken
- // effect.
- event->movementX = event->globalX - global_mouse_position_.x();
- event->movementY = event->globalY - global_mouse_position_.y();
-
- global_mouse_position_.SetPoint(event->globalX, event->globalY);
-
- // Under mouse lock, coordinates of mouse are locked to what they were when
- // mouse lock was entered.
- if (mouse_locked_) {
- event->x = unlocked_mouse_position_.x();
- event->y = unlocked_mouse_position_.y();
- event->windowX = unlocked_mouse_position_.x();
- event->windowY = unlocked_mouse_position_.y();
- event->globalX = unlocked_global_mouse_position_.x();
- event->globalY = unlocked_global_mouse_position_.y();
- } else {
- unlocked_mouse_position_.SetPoint(event->windowX, event->windowY);
- unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY);
- }
-}
-
-void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
- bool is_visible) {
- if (host_->is_hidden() ||
- (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) ||
- (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible))
- return;
-
- cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE;
- host_->SendCursorVisibilityState(is_visible);
-}
-
-void RenderWidgetHostViewAura::SchedulePaintIfNotInClip(
- const gfx::Rect& rect,
- const gfx::Rect& clip) {
- if (!clip.IsEmpty()) {
- gfx::Rect to_paint = gfx::SubtractRects(rect, clip);
- if (!to_paint.IsEmpty())
- window_->SchedulePaintInRect(to_paint);
- } else {
- window_->SchedulePaintInRect(rect);
- }
-}
-
-bool RenderWidgetHostViewAura::ShouldMoveToCenter() {
- gfx::Rect rect = window_->bounds();
- rect = ConvertRectToScreen(rect);
- int border_x = rect.width() * kMouseLockBorderPercentage / 100;
- int border_y = rect.height() * kMouseLockBorderPercentage / 100;
-
- return global_mouse_position_.x() < rect.x() + border_x ||
- global_mouse_position_.x() > rect.right() - border_x ||
- global_mouse_position_.y() < rect.y() + border_y ||
- global_mouse_position_.y() > rect.bottom() - border_y;
-}
-
-void RenderWidgetHostViewAura::RunOnCommitCallbacks() {
- for (std::vector<base::Closure>::const_iterator
- it = on_compositing_did_commit_callbacks_.begin();
- it != on_compositing_did_commit_callbacks_.end(); ++it) {
- it->Run();
- }
- on_compositing_did_commit_callbacks_.clear();
-}
-
-void RenderWidgetHostViewAura::AddOnCommitCallbackAndDisableLocks(
- const base::Closure& callback) {
- ui::Compositor* compositor = GetCompositor();
- DCHECK(compositor);
-
- if (!compositor->HasObserver(this))
- compositor->AddObserver(this);
-
- can_lock_compositor_ = NO_PENDING_COMMIT;
- on_compositing_did_commit_callbacks_.push_back(callback);
-}
-
-void RenderWidgetHostViewAura::AddedToRootWindow() {
- window_->GetRootWindow()->AddRootWindowObserver(this);
- host_->ParentChanged(GetNativeViewId());
- UpdateScreenInfo(window_);
- if (popup_type_ != WebKit::WebPopupTypeNone)
- event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
-
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(window_->GetRootWindow());
- if (cursor_client) {
- cursor_client->AddObserver(this);
- NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
- }
- UpdateExternalTexture();
-}
-
-void RenderWidgetHostViewAura::RemovingFromRootWindow() {
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(window_->GetRootWindow());
- if (cursor_client)
- cursor_client->RemoveObserver(this);
-
- event_filter_for_popup_exit_.reset();
- window_->GetRootWindow()->RemoveRootWindowObserver(this);
- host_->ParentChanged(0);
- ui::Compositor* compositor = GetCompositor();
- // We can't get notification for commits after this point, which would
- // guarantee that the compositor isn't using an old texture any more, so
- // instead we force the texture to NULL which synchronizes with the compositor
- // thread, and makes it safe to run the callback.
- window_->layer()->SetExternalTexture(NULL);
- RunOnCommitCallbacks();
- resize_lock_.reset();
- host_->WasResized();
- if (compositor && compositor->HasObserver(this))
- compositor->RemoveObserver(this);
-}
-
-ui::Compositor* RenderWidgetHostViewAura::GetCompositor() {
- aura::RootWindow* root_window = window_->GetRootWindow();
- return root_window ? root_window->compositor() : NULL;
-}
-
-void RenderWidgetHostViewAura::DetachFromInputMethod() {
- ui::InputMethod* input_method = GetInputMethod();
- if (input_method && input_method->GetTextInputClient() == this)
- input_method->SetFocusedTextInputClient(NULL);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostView, public:
-
-// static
-RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
- RenderWidgetHost* widget) {
- return new RenderWidgetHostViewAura(widget);
-}
-
-// static
-void RenderWidgetHostViewPort::GetDefaultScreenInfo(WebScreenInfo* results) {
- GetScreenInfoForWindow(results, NULL);
-}
-
-} // namespace content
+// 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_aura.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "cc/output/compositor_frame.h"
+#include "cc/output/compositor_frame_ack.h"
+#include "cc/output/copy_output_request.h"
+#include "cc/output/copy_output_result.h"
+#include "cc/resources/texture_mailbox.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "content/browser/renderer_host/backing_store_aura.h"
+#include "content/browser/renderer_host/dip_util.h"
+#include "content/browser/renderer_host/overscroll_controller.h"
+#include "content/browser/renderer_host/render_view_host_delegate.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h"
+#include "content/browser/renderer_host/ui_events_helper.h"
+#include "content/browser/renderer_host/web_input_event_aura.h"
+#include "content/common/gpu/client/gl_helper.h"
+#include "content/common/gpu/gpu_messages.h"
+#include "content/common/view_messages.h"
+#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
+#include "content/port/browser/render_widget_host_view_port.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/user_metrics.h"
+#include "content/public/common/content_switches.h"
+#include "media/base/video_util.h"
+#include "skia/ext/image_operations.h"
+#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/web/WebScreenInfo.h"
+#include "ui/aura/client/activation_client.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/client/cursor_client.h"
+#include "ui/aura/client/cursor_client_observer.h"
+#include "ui/aura/client/focus_client.h"
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/client/stacking_client.h"
+#include "ui/aura/client/tooltip_client.h"
+#include "ui/aura/client/window_types.h"
+#include "ui/aura/env.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_destruction_observer.h"
+#include "ui/aura/window_observer.h"
+#include "ui/aura/window_tracker.h"
+#include "ui/base/clipboard/scoped_clipboard_writer.h"
+#include "ui/base/events/event.h"
+#include "ui/base/events/event_utils.h"
+#include "ui/base/gestures/gesture_recognizer.h"
+#include "ui/base/hit_test.h"
+#include "ui/base/ime/input_method.h"
+#include "ui/base/ui_base_types.h"
+#include "ui/compositor/layer.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/rect_conversions.h"
+#include "ui/gfx/screen.h"
+#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/skia_util.h"
+
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#include "content/browser/accessibility/browser_accessibility_manager_win.h"
+#include "content/browser/accessibility/browser_accessibility_win.h"
+#include "ui/base/win/hidden_window.h"
+#include "ui/gfx/gdi_util.h"
+#endif
+
+using gfx::RectToSkIRect;
+using gfx::SkIRectToRect;
+
+using WebKit::WebScreenInfo;
+using WebKit::WebTouchEvent;
+
+namespace content {
+namespace {
+
+// In mouse lock mode, we need to prevent the (invisible) cursor from hitting
+// the border of the view, in order to get valid movement information. However,
+// forcing the cursor back to the center of the view after each mouse move
+// doesn't work well. It reduces the frequency of useful mouse move messages
+// significantly. Therefore, we move the cursor to the center of the view only
+// if it approaches the border. |kMouseLockBorderPercentage| specifies the width
+// of the border area, in percentage of the corresponding dimension.
+const int kMouseLockBorderPercentage = 15;
+
+// When accelerated compositing is enabled and a widget resize is pending,
+// we delay further resizes of the UI. The following constant is the maximum
+// length of time that we should delay further UI resizes while waiting for a
+// resized frame from a renderer.
+const int kResizeLockTimeoutMs = 67;
+
+#if defined(OS_WIN)
+// Used to associate a plugin HWND with its RenderWidgetHostViewAura instance.
+const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner";
+
+BOOL CALLBACK WindowDestroyingCallback(HWND window, LPARAM param) {
+ RenderWidgetHostViewAura* widget =
+ reinterpret_cast<RenderWidgetHostViewAura*>(param);
+ if (GetProp(window, kWidgetOwnerProperty) == widget) {
+ // Properties set on HWNDs must be removed to avoid leaks.
+ RemoveProp(window, kWidgetOwnerProperty);
+ RenderWidgetHostViewBase::DetachPluginWindowsCallback(window);
+ }
+ return TRUE;
+}
+
+BOOL CALLBACK HideWindowsCallback(HWND window, LPARAM param) {
+ RenderWidgetHostViewAura* widget =
+ reinterpret_cast<RenderWidgetHostViewAura*>(param);
+ if (GetProp(window, kWidgetOwnerProperty) == widget)
+ SetParent(window, ui::GetHiddenWindow());
+ return TRUE;
+}
+
+BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) {
+ RenderWidgetHostViewAura* widget =
+ reinterpret_cast<RenderWidgetHostViewAura*>(param);
+
+ if (GetProp(window, kWidgetOwnerProperty) == widget) {
+ HWND parent =
+ widget->GetNativeView()->GetRootWindow()->GetAcceleratedWidget();
+ SetParent(window, parent);
+ }
+ return TRUE;
+}
+
+struct CutoutRectsParams {
+ RenderWidgetHostViewAura* widget;
+ std::vector<gfx::Rect> cutout_rects;
+ std::map<HWND, WebPluginGeometry>* geometry;
+};
+
+// Used to update the region for the windowed plugin to draw in. We start with
+// the clip rect from the renderer, then remove the cutout rects from the
+// renderer, and then remove the transient windows from the root window and the
+// constrained windows from the parent window.
+BOOL CALLBACK SetCutoutRectsCallback(HWND window, LPARAM param) {
+ CutoutRectsParams* params = reinterpret_cast<CutoutRectsParams*>(param);
+
+ if (GetProp(window, kWidgetOwnerProperty) == params->widget) {
+ // First calculate the offset of this plugin from the root window, since
+ // the cutouts are relative to the root window.
+ HWND parent = params->widget->GetNativeView()->GetRootWindow()->
+ GetAcceleratedWidget();
+ POINT offset;
+ offset.x = offset.y = 0;
+ MapWindowPoints(window, parent, &offset, 1);
+
+ // Now get the cached clip rect and cutouts for this plugin window that came
+ // from the renderer.
+ std::map<HWND, WebPluginGeometry>::iterator i = params->geometry->begin();
+ while (i != params->geometry->end() &&
+ i->second.window != window &&
+ GetParent(i->second.window) != window) {
+ ++i;
+ }
+
+ if (i == params->geometry->end()) {
+ NOTREACHED();
+ return TRUE;
+ }
+
+ HRGN hrgn = CreateRectRgn(i->second.clip_rect.x(),
+ i->second.clip_rect.y(),
+ i->second.clip_rect.right(),
+ i->second.clip_rect.bottom());
+ // We start with the cutout rects that came from the renderer, then add the
+ // ones that came from transient and constrained windows.
+ std::vector<gfx::Rect> cutout_rects = i->second.cutout_rects;
+ for (size_t i = 0; i < params->cutout_rects.size(); ++i) {
+ gfx::Rect offset_cutout = params->cutout_rects[i];
+ offset_cutout.Offset(-offset.x, -offset.y);
+ cutout_rects.push_back(offset_cutout);
+ }
+ gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects);
+ SetWindowRgn(window, hrgn, TRUE);
+ }
+ return TRUE;
+}
+
+// A callback function for EnumThreadWindows to enumerate and dismiss
+// any owned popup windows.
+BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
+ const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);
+
+ if (::IsWindowVisible(window)) {
+ const HWND owner = ::GetWindow(window, GW_OWNER);
+ if (toplevel_hwnd == owner) {
+ ::PostMessage(window, WM_CANCELMODE, 0, 0);
+ }
+ }
+
+ return TRUE;
+}
+#endif
+
+void UpdateWebTouchEventAfterDispatch(WebKit::WebTouchEvent* event,
+ WebKit::WebTouchPoint* point) {
+ if (point->state != WebKit::WebTouchPoint::StateReleased &&
+ point->state != WebKit::WebTouchPoint::StateCancelled)
+ return;
+ --event->touchesLength;
+ for (unsigned i = point - event->touches;
+ i < event->touchesLength;
+ ++i) {
+ event->touches[i] = event->touches[i + 1];
+ }
+}
+
+bool CanRendererHandleEvent(const ui::MouseEvent* event) {
+ if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
+ return false;
+
+#if defined(OS_WIN)
+ // Renderer cannot handle WM_XBUTTON or NC events.
+ switch (event->native_event().message) {
+ case WM_XBUTTONDOWN:
+ case WM_XBUTTONUP:
+ case WM_XBUTTONDBLCLK:
+ case WM_NCMOUSELEAVE:
+ case WM_NCMOUSEMOVE:
+ case WM_NCXBUTTONDOWN:
+ case WM_NCXBUTTONUP:
+ case WM_NCXBUTTONDBLCLK:
+ return false;
+ default:
+ break;
+ }
+#endif
+ return true;
+}
+
+// We don't mark these as handled so that they're sent back to the
+// DefWindowProc so it can generate WM_APPCOMMAND as necessary.
+bool IsXButtonUpEvent(const ui::MouseEvent* event) {
+#if defined(OS_WIN)
+ switch (event->native_event().message) {
+ case WM_XBUTTONUP:
+ case WM_NCXBUTTONUP:
+ return true;
+ }
+#endif
+ return false;
+}
+
+void GetScreenInfoForWindow(WebScreenInfo* results, aura::Window* window) {
+ const gfx::Display display = window ?
+ gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window) :
+ gfx::Screen::GetScreenFor(window)->GetPrimaryDisplay();
+ results->rect = display.bounds();
+ results->availableRect = display.work_area();
+ // TODO(derat|oshima): Don't hardcode this. Get this from display object.
+ results->depth = 24;
+ results->depthPerComponent = 8;
+ results->deviceScaleFactor = display.device_scale_factor();
+}
+
+bool ShouldSendPinchGesture() {
+#if defined(OS_WIN)
+ if (base::win::GetVersion() >= base::win::VERSION_WIN8)
+ return true;
+#endif
+ static bool pinch_allowed =
+ CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableViewport) ||
+ CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePinch);
+ return pinch_allowed;
+}
+
+bool PointerEventActivates(const ui::Event& event) {
+ if (event.type() == ui::ET_MOUSE_PRESSED)
+ return true;
+
+ if (event.type() == ui::ET_GESTURE_BEGIN) {
+ const ui::GestureEvent& gesture =
+ static_cast<const ui::GestureEvent&>(event);
+ return gesture.details().touch_points() == 1;
+ }
+
+ return false;
+}
+
+// Swap ack for the renderer when kCompositeToMailbox is enabled.
+void SendCompositorFrameAck(
+ int32 route_id,
+ uint32 output_surface_id,
+ int renderer_host_id,
+ const gpu::Mailbox& received_mailbox,
+ const gfx::Size& received_size,
+ bool skip_frame,
+ const scoped_refptr<ui::Texture>& texture_to_produce) {
+ cc::CompositorFrameAck ack;
+ ack.gl_frame_data.reset(new cc::GLFrameData());
+ DCHECK(!texture_to_produce.get() || !skip_frame);
+ if (texture_to_produce.get()) {
+ std::string mailbox_name = texture_to_produce->Produce();
+ std::copy(mailbox_name.data(),
+ mailbox_name.data() + mailbox_name.length(),
+ reinterpret_cast<char*>(ack.gl_frame_data->mailbox.name));
+ ack.gl_frame_data->size = texture_to_produce->size();
+ ack.gl_frame_data->sync_point =
+ content::ImageTransportFactory::GetInstance()->InsertSyncPoint();
+ } else if (skip_frame) {
+ // Skip the frame, i.e. tell the producer to reuse the same buffer that
+ // we just received.
+ ack.gl_frame_data->size = received_size;
+ ack.gl_frame_data->mailbox = received_mailbox;
+ }
+
+ RenderWidgetHostImpl::SendSwapCompositorFrameAck(
+ route_id, output_surface_id, renderer_host_id, ack);
+}
+
+void AcknowledgeBufferForGpu(
+ int32 route_id,
+ int gpu_host_id,
+ const std::string& received_mailbox,
+ bool skip_frame,
+ const scoped_refptr<ui::Texture>& texture_to_produce) {
+ AcceleratedSurfaceMsg_BufferPresented_Params ack;
+ uint32 sync_point = 0;
+ DCHECK(!texture_to_produce.get() || !skip_frame);
+ if (texture_to_produce.get()) {
+ ack.mailbox_name = texture_to_produce->Produce();
+ sync_point =
+ content::ImageTransportFactory::GetInstance()->InsertSyncPoint();
+ } else if (skip_frame) {
+ ack.mailbox_name = received_mailbox;
+ ack.sync_point = 0;
+ }
+
+ ack.sync_point = sync_point;
+ RenderWidgetHostImpl::AcknowledgeBufferPresent(
+ route_id, gpu_host_id, ack);
+}
+
+void ReleaseMailbox(scoped_ptr<base::SharedMemory> shared_memory,
+ base::Callback<void()> callback,
+ unsigned sync_point, bool lost_resource) {
+ callback.Run();
+}
+
+} // namespace
+
+// We need to watch for mouse events outside a Web Popup or its parent
+// and dismiss the popup for certain events.
+class RenderWidgetHostViewAura::EventFilterForPopupExit :
+ public ui::EventHandler {
+ public:
+ explicit EventFilterForPopupExit(RenderWidgetHostViewAura* rwhva)
+ : rwhva_(rwhva) {
+ DCHECK(rwhva_);
+ aura::RootWindow* root_window = rwhva_->window_->GetRootWindow();
+ DCHECK(root_window);
+ root_window->AddPreTargetHandler(this);
+ }
+
+ virtual ~EventFilterForPopupExit() {
+ aura::RootWindow* root_window = rwhva_->window_->GetRootWindow();
+ DCHECK(root_window);
+ root_window->RemovePreTargetHandler(this);
+ }
+
+ // Overridden from ui::EventHandler
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+ rwhva_->ApplyEventFilterForPopupExit(event);
+ }
+
+ private:
+ RenderWidgetHostViewAura* rwhva_;
+
+ DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit);
+};
+
+void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
+ ui::MouseEvent* event) {
+ if (in_shutdown_ || is_fullscreen_)
+ return;
+
+ if (event->type() != ui::ET_MOUSE_PRESSED || !event->target())
+ return;
+
+ aura::Window* target = static_cast<aura::Window*>(event->target());
+ if (target != window_ &&
+ (!popup_parent_host_view_ ||
+ target != popup_parent_host_view_->window_)) {
+ // Note: popup_parent_host_view_ may be NULL when there are multiple
+ // popup children per view. See: RenderWidgetHostViewAura::InitAsPopup().
+ in_shutdown_ = true;
+ host_->Shutdown();
+ }
+}
+
+// We have to implement the WindowObserver interface on a separate object
+// because clang doesn't like implementing multiple interfaces that have
+// methods with the same name. This object is owned by the
+// RenderWidgetHostViewAura.
+class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver {
+ public:
+ explicit WindowObserver(RenderWidgetHostViewAura* view)
+ : view_(view) {
+ view_->window_->AddObserver(this);
+ }
+
+ virtual ~WindowObserver() {
+ view_->window_->RemoveObserver(this);
+ }
+
+ // Overridden from aura::WindowObserver:
+ virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
+ if (window == view_->window_)
+ view_->AddedToRootWindow();
+ }
+
+ virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE {
+ if (window == view_->window_)
+ view_->RemovingFromRootWindow();
+ }
+
+ private:
+ RenderWidgetHostViewAura* view_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowObserver);
+};
+
+#if defined(OS_WIN)
+// On Windows, we need to watch the top level window for changes to transient
+// windows because they can cover the view and we need to ensure that they're
+// rendered on top of windowed NPAPI plugins.
+class RenderWidgetHostViewAura::TransientWindowObserver
+ : public aura::WindowObserver {
+ public:
+ explicit TransientWindowObserver(RenderWidgetHostViewAura* view)
+ : view_(view), top_level_(NULL) {
+ view_->window_->AddObserver(this);
+ }
+
+ virtual ~TransientWindowObserver() {
+ view_->window_->RemoveObserver(this);
+ StopObserving();
+ }
+
+ // Overridden from aura::WindowObserver:
+ virtual void OnWindowHierarchyChanged(
+ const aura::WindowObserver::HierarchyChangeParams& params) OVERRIDE {
+ aura::Window* top_level = GetToplevelWindow();
+ if (top_level == top_level_)
+ return;
+
+ StopObserving();
+ top_level_ = top_level;
+ if (top_level_ && top_level_ != view_->window_)
+ top_level_->AddObserver(this);
+ }
+
+ virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
+ if (window == top_level_)
+ StopObserving();
+ }
+
+ virtual void OnWindowBoundsChanged(aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) OVERRIDE {
+ if (window->transient_parent())
+ SendPluginCutoutRects();
+ }
+
+ virtual void OnWindowVisibilityChanged(aura::Window* window,
+ bool visible) OVERRIDE {
+ if (window->transient_parent())
+ SendPluginCutoutRects();
+ }
+
+ virtual void OnAddTransientChild(aura::Window* window,
+ aura::Window* transient) OVERRIDE {
+ transient->AddObserver(this);
+ // Just wait for the OnWindowBoundsChanged of the transient, since the size
+ // is not known now.
+ }
+
+ virtual void OnRemoveTransientChild(aura::Window* window,
+ aura::Window* transient) OVERRIDE {
+ transient->RemoveObserver(this);
+ SendPluginCutoutRects();
+ }
+
+ aura::Window* GetToplevelWindow() {
+ aura::RootWindow* root = view_->window_->GetRootWindow();
+ if (!root)
+ return NULL;
+ aura::client::ActivationClient* activation_client =
+ aura::client::GetActivationClient(root);
+ if (!activation_client)
+ return NULL;
+ return activation_client->GetToplevelWindow(view_->window_);
+ }
+
+ void StopObserving() {
+ if (!top_level_)
+ return;
+
+ const aura::Window::Windows& transients = top_level_->transient_children();
+ for (size_t i = 0; i < transients.size(); ++i)
+ transients[i]->RemoveObserver(this);
+
+ if (top_level_ != view_->window_)
+ top_level_->RemoveObserver(this);
+ top_level_ = NULL;
+ }
+
+ void SendPluginCutoutRects() {
+ std::vector<gfx::Rect> cutouts;
+ if (top_level_) {
+ const aura::Window::Windows& transients =
+ top_level_->transient_children();
+ for (size_t i = 0; i < transients.size(); ++i) {
+ if (transients[i]->IsVisible())
+ cutouts.push_back(transients[i]->GetBoundsInRootWindow());
+ }
+ }
+
+ view_->UpdateTransientRects(cutouts);
+ }
+ private:
+ RenderWidgetHostViewAura* view_;
+ aura::Window* top_level_;
+
+ DISALLOW_COPY_AND_ASSIGN(TransientWindowObserver);
+};
+
+#endif
+
+class RenderWidgetHostViewAura::ResizeLock {
+ public:
+ ResizeLock(aura::RootWindow* root_window,
+ const gfx::Size new_size,
+ bool defer_compositor_lock)
+ : root_window_(root_window),
+ new_size_(new_size),
+ compositor_lock_(defer_compositor_lock ?
+ NULL :
+ root_window_->compositor()->GetCompositorLock()),
+ weak_ptr_factory_(this),
+ defer_compositor_lock_(defer_compositor_lock) {
+ TRACE_EVENT_ASYNC_BEGIN2("ui", "ResizeLock", this,
+ "width", new_size_.width(),
+ "height", new_size_.height());
+ root_window_->HoldPointerMoves();
+
+ BrowserThread::PostDelayedTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&RenderWidgetHostViewAura::ResizeLock::CancelLock,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs));
+ }
+
+ ~ResizeLock() {
+ CancelLock();
+ TRACE_EVENT_ASYNC_END2("ui", "ResizeLock", this,
+ "width", new_size_.width(),
+ "height", new_size_.height());
+ }
+
+ void UnlockCompositor() {
+ defer_compositor_lock_ = false;
+ compositor_lock_ = NULL;
+ }
+
+ void CancelLock() {
+ if (!root_window_)
+ return;
+ UnlockCompositor();
+ root_window_->ReleasePointerMoves();
+ root_window_ = NULL;
+ }
+
+ const gfx::Size& expected_size() const {
+ return new_size_;
+ }
+
+ bool GrabDeferredLock() {
+ if (root_window_ && defer_compositor_lock_) {
+ compositor_lock_ = root_window_->compositor()->GetCompositorLock();
+ defer_compositor_lock_ = false;
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ aura::RootWindow* root_window_;
+ gfx::Size new_size_;
+ scoped_refptr<ui::CompositorLock> compositor_lock_;
+ base::WeakPtrFactory<ResizeLock> weak_ptr_factory_;
+ bool defer_compositor_lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResizeLock);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, public:
+
+RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
+ : host_(RenderWidgetHostImpl::From(host)),
+ window_(new aura::Window(this)),
+ in_shutdown_(false),
+ is_fullscreen_(false),
+ popup_parent_host_view_(NULL),
+ popup_child_host_view_(NULL),
+ is_loading_(false),
+ text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
+ can_compose_inline_(true),
+ has_composition_text_(false),
+ last_swapped_surface_scale_factor_(1.f),
+ paint_canvas_(NULL),
+ synthetic_move_sent_(false),
+ accelerated_compositing_state_changed_(false),
+ can_lock_compositor_(YES),
+ cursor_visibility_state_in_renderer_(UNKNOWN),
+ paint_observer_(NULL),
+ touch_editing_client_(NULL) {
+ host_->SetView(this);
+ window_observer_.reset(new WindowObserver(this));
+ aura::client::SetTooltipText(window_, &tooltip_);
+ aura::client::SetActivationDelegate(window_, this);
+ aura::client::SetActivationChangeObserver(window_, this);
+ aura::client::SetFocusChangeObserver(window_, this);
+ gfx::Screen::GetScreenFor(window_)->AddObserver(this);
+#if defined(OS_WIN)
+ transient_observer_.reset(new TransientWindowObserver(this));
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, RenderWidgetHostView implementation:
+
+void RenderWidgetHostViewAura::InitAsChild(
+ gfx::NativeView parent_view) {
+ window_->Init(ui::LAYER_TEXTURED);
+ window_->SetName("RenderWidgetHostViewAura");
+}
+
+void RenderWidgetHostViewAura::InitAsPopup(
+ RenderWidgetHostView* parent_host_view,
+ const gfx::Rect& bounds_in_screen) {
+ popup_parent_host_view_ =
+ static_cast<RenderWidgetHostViewAura*>(parent_host_view);
+
+ RenderWidgetHostViewAura* old_child =
+ popup_parent_host_view_->popup_child_host_view_;
+ if (old_child) {
+ // TODO(jhorwich): Allow multiple popup_child_host_view_ per view, or
+ // similar mechanism to ensure a second popup doesn't cause the first one
+ // to never get a chance to filter events. See crbug.com/160589.
+ DCHECK(old_child->popup_parent_host_view_ == popup_parent_host_view_);
+ old_child->popup_parent_host_view_ = NULL;
+ }
+ popup_parent_host_view_->popup_child_host_view_ = this;
+ window_->SetType(aura::client::WINDOW_TYPE_MENU);
+ window_->Init(ui::LAYER_TEXTURED);
+ window_->SetName("RenderWidgetHostViewAura");
+
+ aura::RootWindow* root = popup_parent_host_view_->window_->GetRootWindow();
+ window_->SetDefaultParentByRootWindow(root, bounds_in_screen);
+
+ SetBounds(bounds_in_screen);
+ Show();
+}
+
+void RenderWidgetHostViewAura::InitAsFullscreen(
+ RenderWidgetHostView* reference_host_view) {
+ is_fullscreen_ = true;
+ window_->SetType(aura::client::WINDOW_TYPE_NORMAL);
+ window_->Init(ui::LAYER_TEXTURED);
+ window_->SetName("RenderWidgetHostViewAura");
+ window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
+
+ aura::RootWindow* parent = NULL;
+ gfx::Rect bounds;
+ if (reference_host_view) {
+ aura::Window* reference_window =
+ static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_;
+ if (reference_window) {
+ host_tracker_.reset(new aura::WindowTracker);
+ host_tracker_->Add(reference_window);
+ }
+ gfx::Display display = gfx::Screen::GetScreenFor(window_)->
+ GetDisplayNearestWindow(reference_window);
+ parent = reference_window->GetRootWindow();
+ bounds = display.bounds();
+ }
+
+ window_->SetDefaultParentByRootWindow(parent, bounds);
+ Show();
+ Focus();
+}
+
+RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
+ return host_;
+}
+
+void RenderWidgetHostViewAura::WasShown() {
+ if (!host_->is_hidden())
+ return;
+ host_->WasShown();
+
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(window_->GetRootWindow());
+ if (cursor_client)
+ NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
+
+ if (!current_surface_.get() && host_->is_accelerated_compositing_active() &&
+ !released_front_lock_.get()) {
+ released_front_lock_ = GetCompositor()->GetCompositorLock();
+ }
+
+#if defined(OS_WIN)
+ LPARAM lparam = reinterpret_cast<LPARAM>(this);
+ EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
+ transient_observer_->SendPluginCutoutRects();
+#endif
+}
+
+void RenderWidgetHostViewAura::WasHidden() {
+ if (host_->is_hidden())
+ return;
+ host_->WasHidden();
+
+ released_front_lock_ = NULL;
+
+#if defined(OS_WIN)
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ if (root_window) {
+ HWND parent = root_window->GetAcceleratedWidget();
+ LPARAM lparam = reinterpret_cast<LPARAM>(this);
+
+ EnumChildWindows(parent, HideWindowsCallback, lparam);
+ }
+#endif
+}
+
+void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) {
+ // For a set size operation, we don't care what coordinate system the origin
+ // of the window is stored in, it's only important to make sure the origin
+ // remains constant after the operation.
+ InternalSetBounds(gfx::Rect(window_->bounds().origin(), size));
+}
+
+void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
+ // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but
+ // Window::SetBounds() takes parent coordinates, so we do the conversion here.
+ aura::RootWindow* root = window_->GetRootWindow();
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(root);
sky 2013/07/25 14:55:31 nit: indent 2 more.
+ gfx::Point origin_in_parent(rect.origin());
+ if (screen_position_client) {
+ screen_position_client->ConvertPointFromScreen(
+ window_->parent(), &origin_in_parent);
+ }
+
+ InternalSetBounds(gfx::Rect(origin_in_parent, rect.size()));
+}
+
+void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
sky 2013/07/25 14:55:31 Make position match that of header.
zturner 2013/07/25 17:41:08 Ahh, I actually thought I had, but I positioned it
+ if (HasDisplayPropertyChanged(window_))
+ host_->InvalidateScreenInfo();
+
+ window_->SetBounds(rect);
+ host_->WasResized();
+ MaybeCreateResizeLock();
+ if (touch_editing_client_) {
+ touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
+ selection_focus_rect_);
+ }
+}
+
+void RenderWidgetHostViewAura::MaybeCreateResizeLock() {
+ gfx::Size desired_size = window_->bounds().size();
+ if (!host_->should_auto_resize() &&
+ !resize_lock_.get() &&
+ desired_size != current_frame_size_ &&
+ host_->is_accelerated_compositing_active()) {
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ ui::Compositor* compositor = root_window ?
+ root_window->compositor() : NULL;
+ if (root_window && compositor) {
+ // Listen to changes in the compositor lock state.
+ if (!compositor->HasObserver(this))
+ compositor->AddObserver(this);
+
+// On Windows while resizing, the the resize locks makes us mis-paint a white
+// vertical strip (including the non-client area) if the content composition is
+// lagging the UI composition. So here we disable the throttling so that the UI
+// bits can draw ahead of the content thereby reducing the amount of whiteout.
+// Because this causes the content to be drawn at wrong sizes while resizing
+// we compensate by blocking the UI thread in Compositor::Draw() by issuing a
+// FinishAllRendering() if we are resizing.
+#if !defined (OS_WIN)
+ bool defer_compositor_lock =
+ can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
+ can_lock_compositor_ == NO_PENDING_COMMIT;
+
+ if (can_lock_compositor_ == YES)
+ can_lock_compositor_ = YES_DID_LOCK;
+
+ resize_lock_.reset(new ResizeLock(root_window, desired_size,
+ defer_compositor_lock));
+#endif
+ }
+ }
+}
+
+gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
+ return window_;
+}
+
+gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const {
+#if defined(OS_WIN)
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ if (root_window) {
+ HWND window = root_window->GetAcceleratedWidget();
+ return reinterpret_cast<gfx::NativeViewId>(window);
+ }
+#endif
+ return static_cast<gfx::NativeViewId>(NULL);
+}
+
+gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
+#if defined(OS_WIN)
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ if (!root_window)
+ return static_cast<gfx::NativeViewAccessible>(NULL);
+ HWND hwnd = root_window->GetAcceleratedWidget();
+
+ BrowserAccessibilityManager* manager =
+ GetOrCreateBrowserAccessibilityManager();
+ if (manager)
+ return manager->GetRoot()->ToBrowserAccessibilityWin();
+#endif
+
+ NOTIMPLEMENTED();
+ return static_cast<gfx::NativeViewAccessible>(NULL);
+}
+
+BrowserAccessibilityManager*
+RenderWidgetHostViewAura::GetOrCreateBrowserAccessibilityManager() {
+ BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
+ if (manager)
+ return manager;
+
+#if defined(OS_WIN)
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ if (!root_window)
+ return NULL;
+ HWND hwnd = root_window->GetAcceleratedWidget();
+
+ // The accessible_parent may be NULL at this point. The WebContents will pass
+ // it down to this instance (by way of the RenderViewHost and
+ // RenderWidgetHost) when it is known. This instance will then set it on its
+ // BrowserAccessibilityManager.
+ gfx::NativeViewAccessible accessible_parent =
+ host_->GetParentNativeViewAccessible();
+
+ manager = new BrowserAccessibilityManagerWin(
+ hwnd, accessible_parent,
+ BrowserAccessibilityManagerWin::GetEmptyDocument(), this);
+#else
+ manager = BrowserAccessibilityManager::Create(
+ BrowserAccessibilityManager::GetEmptyDocument(), this);
+#endif
+
+ SetBrowserAccessibilityManager(manager);
+ return manager;
+}
+
+void RenderWidgetHostViewAura::MovePluginWindows(
+ const gfx::Vector2d& scroll_offset,
+ const std::vector<WebPluginGeometry>& plugin_window_moves) {
+#if defined(OS_WIN)
+ // We need to clip the rectangle to the tab's viewport, otherwise we will draw
+ // over the browser UI.
+ if (!window_->GetRootWindow()) {
+ DCHECK(plugin_window_moves.empty());
+ return;
+ }
+ HWND parent = window_->GetRootWindow()->GetAcceleratedWidget();
+ gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
+ std::vector<WebPluginGeometry> moves = plugin_window_moves;
+
+ gfx::Rect view_port(scroll_offset.x(), scroll_offset.y(), view_bounds.width(),
+ view_bounds.height());
+
+ for (size_t i = 0; i < moves.size(); ++i) {
+ gfx::Rect clip(moves[i].clip_rect);
+ gfx::Vector2d view_port_offset(
+ moves[i].window_rect.OffsetFromOrigin() + scroll_offset);
+ clip.Offset(view_port_offset);
+ clip.Intersect(view_port);
+ clip.Offset(-view_port_offset);
+ moves[i].clip_rect = clip;
+
+ moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin());
+
+ plugin_window_moves_[moves[i].window] = moves[i];
+
+ // transient_rects_ and constrained_rects_ are relative to the root window.
+ // We want to convert them to be relative to the plugin window.
+ std::vector<gfx::Rect> cutout_rects;
+ cutout_rects.assign(transient_rects_.begin(), transient_rects_.end());
+ cutout_rects.insert(cutout_rects.end(), constrained_rects_.begin(),
+ constrained_rects_.end());
+ for (size_t j = 0; j < cutout_rects.size(); ++j) {
+ gfx::Rect offset_cutout = cutout_rects[j];
+ offset_cutout -= moves[i].window_rect.OffsetFromOrigin();
+ moves[i].cutout_rects.push_back(offset_cutout);
+ }
+ }
+
+ MovePluginWindowsHelper(parent, moves);
+
+ // Make sure each plugin window (or its wrapper if it exists) has a pointer to
+ // |this|.
+ for (size_t i = 0; i < moves.size(); ++i) {
+ HWND window = moves[i].window;
+ if (GetParent(window) != parent) {
+ window = GetParent(window);
+ DCHECK(GetParent(window) == parent);
+ }
+ if (!GetProp(window, kWidgetOwnerProperty))
+ CHECK(SetProp(window, kWidgetOwnerProperty, this));
+ }
+#endif // defined(OS_WIN)
+}
+
+void RenderWidgetHostViewAura::Focus() {
+ // Make sure we have a FocusClient before attempting to Focus(). In some
+ // situations we may not yet be in a valid Window hierarchy (such as reloading
+ // after out of memory discarded the tab).
+ aura::client::FocusClient* client = aura::client::GetFocusClient(window_);
+ if (client)
+ window_->Focus();
+}
+
+void RenderWidgetHostViewAura::Blur() {
+ window_->Blur();
+}
+
+bool RenderWidgetHostViewAura::HasFocus() const {
+ return window_->HasFocus();
+}
+
+bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
+ return window_->layer()->has_external_content() ||
+ !!host_->GetBackingStore(false);
+}
+
+void RenderWidgetHostViewAura::Show() {
+ window_->Show();
+}
+
+void RenderWidgetHostViewAura::Hide() {
+ window_->Hide();
+}
+
+bool RenderWidgetHostViewAura::IsShowing() {
+ return window_->IsVisible();
+}
+
+gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
+ // This is the size that we want the renderer to produce. While we're waiting
+ // for the correct frame (i.e. during a resize), don't change the size so that
+ // we don't pipeline more resizes than we can handle.
+ gfx::Rect bounds(window_->GetBoundsInScreen());
+ if (resize_lock_.get())
+ return gfx::Rect(bounds.origin(), resize_lock_->expected_size());
+ else
+ return bounds;
+}
+
+void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) {
+ RenderWidgetHostViewBase::SetBackground(background);
+ host_->SetBackground(background);
+ window_->layer()->SetFillsBoundsOpaquely(background.isOpaque());
+}
+
+#if defined(OS_WIN)
+gfx::NativeViewAccessible
+RenderWidgetHostViewAura::AccessibleObjectFromChildId(long child_id) {
+ BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
+ if (!manager)
+ return NULL;
+
+ return manager->ToBrowserAccessibilityManagerWin()->GetFromUniqueIdWin(
+ child_id);
+}
+#endif // defined(OS_WIN)
+
+void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
+ current_cursor_ = cursor;
+ const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
+ GetDisplayNearestWindow(window_);
+ current_cursor_.SetDeviceScaleFactor(display.device_scale_factor());
+ UpdateCursorIfOverSelf();
+}
+
+void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
+ if (is_loading_ && !is_loading && paint_observer_)
+ paint_observer_->OnPageLoadComplete();
+ is_loading_ = is_loading;
+ UpdateCursorIfOverSelf();
+}
+
+void RenderWidgetHostViewAura::TextInputTypeChanged(
+ ui::TextInputType type,
+ bool can_compose_inline,
+ ui::TextInputMode input_mode) {
+ if (text_input_type_ != type ||
+ can_compose_inline_ != can_compose_inline) {
+ text_input_type_ = type;
+ can_compose_inline_ = can_compose_inline;
+ if (GetInputMethod())
+ GetInputMethod()->OnTextInputTypeChanged(this);
+ if (touch_editing_client_)
+ touch_editing_client_->OnTextInputTypeChanged(text_input_type_);
+ }
+}
+
+void RenderWidgetHostViewAura::ImeCancelComposition() {
+ if (GetInputMethod())
+ GetInputMethod()->CancelComposition(this);
+ has_composition_text_ = false;
+}
+
+void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
+ const ui::Range& range,
+ const std::vector<gfx::Rect>& character_bounds) {
+ composition_character_bounds_ = character_bounds;
+}
+
+void RenderWidgetHostViewAura::DidUpdateBackingStore(
+ const gfx::Rect& scroll_rect,
+ const gfx::Vector2d& scroll_delta,
+ const std::vector<gfx::Rect>& copy_rects,
+ const ui::LatencyInfo& latency_info) {
+ if (accelerated_compositing_state_changed_)
+ UpdateExternalTexture();
+
+ software_latency_info_.MergeWith(latency_info);
+
+ // Use the state of the RenderWidgetHost and not the window as the two may
+ // differ. In particular if the window is hidden but the renderer isn't and we
+ // ignore the update and the window is made visible again the layer isn't
+ // marked as dirty and we show the wrong thing.
+ // We do this after UpdateExternalTexture() so that when we become visible
+ // we're not drawing a stale texture.
+ if (host_->is_hidden())
+ return;
+
+ gfx::Rect clip_rect;
+ if (paint_canvas_) {
+ SkRect sk_clip_rect;
+ if (paint_canvas_->sk_canvas()->getClipBounds(&sk_clip_rect))
+ clip_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(sk_clip_rect));
+ }
+
+ if (!scroll_rect.IsEmpty())
+ SchedulePaintIfNotInClip(scroll_rect, clip_rect);
+
+#if defined(OS_WIN)
+ aura::RootWindow* root_window = window_->GetRootWindow();
+#endif
+ for (size_t i = 0; i < copy_rects.size(); ++i) {
+ gfx::Rect rect = gfx::SubtractRects(copy_rects[i], scroll_rect);
+ if (rect.IsEmpty())
+ continue;
+
+ SchedulePaintIfNotInClip(rect, clip_rect);
+
+#if defined(OS_WIN)
+ if (root_window) {
+ // Send the invalid rect in screen coordinates.
+ gfx::Rect screen_rect = GetViewBounds();
+ gfx::Rect invalid_screen_rect(rect);
+ invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y());
+ HWND hwnd = root_window->GetAcceleratedWidget();
+ PaintPluginWindowsHelper(hwnd, invalid_screen_rect);
+ }
+#endif // defined(OS_WIN)
+ }
+}
+
+void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
+ int error_code) {
+ UpdateCursorIfOverSelf();
+ Destroy();
+}
+
+void RenderWidgetHostViewAura::Destroy() {
+ // Beware, this function is not called on all destruction paths. It will
+ // implicitly end up calling ~RenderWidgetHostViewAura though, so all
+ // destruction/cleanup code should happen there, not here.
+ in_shutdown_ = true;
+ delete window_;
+}
+
+void RenderWidgetHostViewAura::SetTooltipText(const string16& tooltip_text) {
+ tooltip_ = tooltip_text;
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ aura::client::TooltipClient* tooltip_client =
+ aura::client::GetTooltipClient(root_window);
+ if (tooltip_client) {
+ tooltip_client->UpdateTooltip(window_);
+ // Content tooltips should be visible indefinitely.
+ tooltip_client->SetTooltipShownTimeout(window_, 0);
+ }
+}
+
+void RenderWidgetHostViewAura::SelectionChanged(const string16& text,
+ size_t offset,
+ const ui::Range& range) {
+ RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
+
+#if defined(USE_X11) && !defined(OS_CHROMEOS)
+ if (text.empty() || range.is_empty())
+ return;
+
+ // Set the BUFFER_SELECTION to the ui::Clipboard.
+ ui::ScopedClipboardWriter clipboard_writer(
+ ui::Clipboard::GetForCurrentThread(),
+ ui::Clipboard::BUFFER_SELECTION);
+ clipboard_writer.WriteText(text);
+#endif // defined(USE_X11) && !defined(OS_CHROMEOS)
+}
+
+void RenderWidgetHostViewAura::SelectionBoundsChanged(
+ const ViewHostMsg_SelectionBounds_Params& params) {
+ if (selection_anchor_rect_ == params.anchor_rect &&
+ selection_focus_rect_ == params.focus_rect)
+ return;
+
+ selection_anchor_rect_ = params.anchor_rect;
+ selection_focus_rect_ = params.focus_rect;
+
+ if (GetInputMethod())
+ GetInputMethod()->OnCaretBoundsChanged(this);
+
+ if (touch_editing_client_) {
+ touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
+ selection_focus_rect_);
+ }
+}
+
+void RenderWidgetHostViewAura::ScrollOffsetChanged() {
+ aura::RootWindow* root = window_->GetRootWindow();
+ if (!root)
+ return;
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(root);
+ if (cursor_client && !cursor_client->IsCursorVisible())
+ cursor_client->DisableMouseEvents();
+}
+
+BackingStore* RenderWidgetHostViewAura::AllocBackingStore(
+ const gfx::Size& size) {
+ return new BackingStoreAura(host_, size);
+}
+
+void RenderWidgetHostViewAura::CopyFromCompositingSurface(
+ const gfx::Rect& src_subrect,
+ const gfx::Size& dst_size,
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
+ if (!window_->layer()->has_external_content()) {
+ callback.Run(false, SkBitmap());
+ return;
+ }
+
+ const gfx::Size& dst_size_in_pixel = ConvertViewSizeToPixel(this, dst_size);
+
+ scoped_ptr<cc::CopyOutputRequest> request =
+ cc::CopyOutputRequest::CreateRequest(base::Bind(
+ &RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult,
+ dst_size_in_pixel,
+ callback));
+ request->set_area(src_subrect);
+ window_->layer()->RequestCopyOfOutput(request.Pass());
+}
+
+void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
+ const gfx::Rect& src_subrect,
+ const scoped_refptr<media::VideoFrame>& target,
+ const base::Callback<void(bool)>& callback) {
+ if (!window_->layer()->has_external_content()) {
+ callback.Run(false);
+ return;
+ }
+
+ scoped_ptr<cc::CopyOutputRequest> request =
+ cc::CopyOutputRequest::CreateRequest(base::Bind(
+ &RenderWidgetHostViewAura::
+ CopyFromCompositingSurfaceHasResultForVideo,
+ AsWeakPtr(), // For caching the ReadbackYUVInterface on this class.
+ target,
+ callback));
+ request->set_area(src_subrect);
+ window_->layer()->RequestCopyOfOutput(request.Pass());
+}
+
+bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
+ // TODO(skaslev): Implement this path for s/w compositing.
+ return window_->layer()->has_external_content() &&
+ host_->is_accelerated_compositing_active();
+}
+
+bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
+ return true;
+}
+
+void RenderWidgetHostViewAura::BeginFrameSubscription(
+ scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
+ frame_subscriber_ = subscriber.Pass();
+}
+
+void RenderWidgetHostViewAura::EndFrameSubscription() {
+ frame_subscriber_.reset();
+}
+
+
+void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() {
+ // Delay processing the state change until we either get a software frame if
+ // switching to software mode or receive a buffers swapped notification
+ // if switching to accelerated mode.
+ // Sometimes (e.g. on a page load) the renderer will spuriously disable then
+ // re-enable accelerated compositing, causing us to flash.
+ // TODO(piman): factor the enable/disable accelerated compositing message into
+ // the UpdateRect/AcceleratedSurfaceBuffersSwapped messages so that we have
+ // fewer inconsistent temporary states.
+ accelerated_compositing_state_changed_ = true;
+}
+
+bool RenderWidgetHostViewAura::ShouldSkipFrame(gfx::Size size_in_dip) const {
+ if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
+ can_lock_compositor_ == NO_PENDING_COMMIT ||
+ !resize_lock_.get())
+ return false;
+
+ return size_in_dip != resize_lock_->expected_size();
+}
+
+void RenderWidgetHostViewAura::CheckResizeLock() {
+ if (!resize_lock_ || resize_lock_->expected_size() != current_frame_size_)
+ return;
+
+ // Since we got the size we were looking for, unlock the compositor. But delay
+ // the release of the lock until we've kicked a frame with the new texture, to
+ // avoid resizing the UI before we have a chance to draw a "good" frame.
+ resize_lock_->UnlockCompositor();
+ ui::Compositor* compositor = GetCompositor();
+ if (compositor) {
+ if (!compositor->HasObserver(this))
+ compositor->AddObserver(this);
+ }
+}
+
+void RenderWidgetHostViewAura::UpdateExternalTexture() {
+ // Delay processing accelerated compositing state change till here where we
+ // act upon the state change. (Clear the external texture if switching to
+ // software mode or set the external texture if going to accelerated mode).
+ if (accelerated_compositing_state_changed_)
+ accelerated_compositing_state_changed_ = false;
+
+ bool is_compositing_active = host_->is_accelerated_compositing_active();
+ if (is_compositing_active && current_surface_.get()) {
+ window_->layer()->SetExternalTexture(current_surface_.get());
+ current_frame_size_ = ConvertSizeToDIP(
+ current_surface_->device_scale_factor(), current_surface_->size());
+ CheckResizeLock();
+ } else if (is_compositing_active &&
+ current_software_frame_.IsSharedMemory()) {
+ window_->layer()->SetTextureMailbox(current_software_frame_,
+ last_swapped_surface_scale_factor_);
+ current_frame_size_ = ConvertSizeToDIP(
+ last_swapped_surface_scale_factor_,
+ current_software_frame_.shared_memory_size());
+ CheckResizeLock();
+ } else {
+ window_->layer()->SetExternalTexture(NULL);
+ resize_lock_.reset();
+ host_->WasResized();
+ }
+}
+
+bool RenderWidgetHostViewAura::SwapBuffersPrepare(
+ const gfx::Rect& surface_rect,
+ float surface_scale_factor,
+ const gfx::Rect& damage_rect,
+ const std::string& mailbox_name,
+ const BufferPresentedCallback& ack_callback) {
+ if (last_swapped_surface_size_ != surface_rect.size()) {
+ // The surface could have shrunk since we skipped an update, in which
+ // case we can expect a full update.
+ DLOG_IF(ERROR, damage_rect != surface_rect) << "Expected full damage rect";
+ skipped_damage_.setEmpty();
+ last_swapped_surface_size_ = surface_rect.size();
+ last_swapped_surface_scale_factor_ = surface_scale_factor;
+ }
+
+ if (ShouldSkipFrame(ConvertSizeToDIP(surface_scale_factor,
+ surface_rect.size())) ||
+ mailbox_name.empty()) {
+ skipped_damage_.op(RectToSkIRect(damage_rect), SkRegion::kUnion_Op);
+ ack_callback.Run(true, scoped_refptr<ui::Texture>());
+ return false;
+ }
+
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ current_surface_ =
+ factory->CreateTransportClient(surface_scale_factor);
+ if (!current_surface_.get()) {
+ LOG(ERROR) << "Failed to create ImageTransport texture";
+ ack_callback.Run(true, scoped_refptr<ui::Texture>());
+ return false;
+ }
+
+ current_surface_->Consume(mailbox_name, surface_rect.size());
+ released_front_lock_ = NULL;
+ UpdateExternalTexture();
+
+ return true;
+}
+
+void RenderWidgetHostViewAura::SwapBuffersCompleted(
+ const BufferPresentedCallback& ack_callback,
+ const scoped_refptr<ui::Texture>& texture_to_return) {
+ ui::Compositor* compositor = GetCompositor();
+
+ if (frame_subscriber() && current_surface_.get() != NULL) {
+ const base::Time present_time = base::Time::Now();
+ scoped_refptr<media::VideoFrame> frame;
+ RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
+ if (frame_subscriber()->ShouldCaptureFrame(present_time,
+ &frame, &callback)) {
+ CopyFromCompositingSurfaceToVideoFrame(
+ gfx::Rect(ConvertSizeToDIP(current_surface_->device_scale_factor(),
+ current_surface_->size())),
+ frame,
+ base::Bind(callback, present_time));
+ }
+ }
+
+ if (!compositor) {
+ ack_callback.Run(false, texture_to_return);
+ } else {
+ AddOnCommitCallbackAndDisableLocks(
+ base::Bind(ack_callback, false, texture_to_return));
+ }
+}
+
+#if defined(OS_WIN)
+void RenderWidgetHostViewAura::UpdateTransientRects(
+ const std::vector<gfx::Rect>& rects) {
+ transient_rects_ = rects;
+ UpdateCutoutRects();
+}
+
+void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
+ const std::vector<gfx::Rect>& rects) {
+ constrained_rects_ = rects;
+ UpdateCutoutRects();
+}
+
+void RenderWidgetHostViewAura::UpdateCutoutRects() {
+ if (!window_->GetRootWindow())
+ return;
+ HWND parent = window_->GetRootWindow()->GetAcceleratedWidget();
+ CutoutRectsParams params;
+ params.widget = this;
+ params.cutout_rects.assign(transient_rects_.begin(), transient_rects_.end());
+ params.cutout_rects.insert(params.cutout_rects.end(),
+ constrained_rects_.begin(),
+ constrained_rects_.end());
+ params.geometry = &plugin_window_moves_;
+ LPARAM lparam = reinterpret_cast<LPARAM>(&params);
+ EnumChildWindows(parent, SetCutoutRectsCallback, lparam);
+}
+#endif
+
+void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
+ const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
+ int gpu_host_id) {
+ BufferPresentedCallback ack_callback = base::Bind(
+ &AcknowledgeBufferForGpu,
+ params_in_pixel.route_id,
+ gpu_host_id,
+ params_in_pixel.mailbox_name);
+ BuffersSwapped(params_in_pixel.size,
+ gfx::Rect(params_in_pixel.size),
+ params_in_pixel.scale_factor,
+ params_in_pixel.mailbox_name,
+ params_in_pixel.latency_info,
+ ack_callback);
+}
+
+void RenderWidgetHostViewAura::SwapDelegatedFrame(
+ uint32 output_surface_id,
+ scoped_ptr<cc::DelegatedFrameData> frame_data,
+ float frame_device_scale_factor,
+ const ui::LatencyInfo& latency_info) {
+ gfx::Size frame_size_in_dip;
+ if (!frame_data->render_pass_list.empty()) {
+ frame_size_in_dip = gfx::ToFlooredSize(gfx::ScaleSize(
+ frame_data->render_pass_list.back()->output_rect.size(),
+ 1.f/frame_device_scale_factor));
+ }
+ if (ShouldSkipFrame(frame_size_in_dip)) {
+ cc::CompositorFrameAck ack;
+ ack.resources.swap(frame_data->resource_list);
+ RenderWidgetHostImpl::SendSwapCompositorFrameAck(
+ host_->GetRoutingID(), output_surface_id,
+ host_->GetProcess()->GetID(), ack);
+ return;
+ }
+ window_->layer()->SetDelegatedFrame(frame_data.Pass(), frame_size_in_dip);
+ released_front_lock_ = NULL;
+ current_frame_size_ = frame_size_in_dip;
+ CheckResizeLock();
+
+ if (paint_observer_)
+ paint_observer_->OnUpdateCompositorContent();
+
+ ui::Compositor* compositor = GetCompositor();
+ if (!compositor) {
+ SendDelegatedFrameAck(output_surface_id);
+ } else {
+ compositor->SetLatencyInfo(latency_info);
+ AddOnCommitCallbackAndDisableLocks(
+ base::Bind(&RenderWidgetHostViewAura::SendDelegatedFrameAck,
+ AsWeakPtr(),
+ output_surface_id));
+ }
+}
+
+void RenderWidgetHostViewAura::SendDelegatedFrameAck(uint32 output_surface_id) {
+ cc::CompositorFrameAck ack;
+ window_->layer()->TakeUnusedResourcesForChildCompositor(&ack.resources);
+ RenderWidgetHostImpl::SendSwapCompositorFrameAck(
+ host_->GetRoutingID(), output_surface_id,
+ host_->GetProcess()->GetID(), ack);
+}
+
+void RenderWidgetHostViewAura::SwapSoftwareFrame(
+ uint32 output_surface_id,
+ scoped_ptr<cc::SoftwareFrameData> frame_data,
+ float frame_device_scale_factor,
+ const ui::LatencyInfo& latency_info) {
+ const gfx::Size& frame_size = frame_data->size;
+ const gfx::Rect& damage_rect = frame_data->damage_rect;
+ gfx::Size frame_size_in_dip =
+ ConvertSizeToDIP(frame_device_scale_factor, frame_size);
+ if (ShouldSkipFrame(frame_size_in_dip)) {
+ SendSoftwareFrameAck(output_surface_id, frame_data->id);
+ return;
+ }
+
+ const size_t size_in_bytes = 4 * frame_size.GetArea();
+#ifdef OS_WIN
+ scoped_ptr<base::SharedMemory> shared_memory(
+ new base::SharedMemory(frame_data->handle, true,
+ host_->GetProcess()->GetHandle()));
+#else
+ scoped_ptr<base::SharedMemory> shared_memory(
+ new base::SharedMemory(frame_data->handle, true));
+#endif
+
+ if (!shared_memory->Map(size_in_bytes)) {
+ host_->GetProcess()->ReceivedBadMessage();
+ return;
+ }
+
+ if (last_swapped_surface_size_ != frame_size) {
+ DLOG_IF(ERROR, damage_rect != gfx::Rect(frame_size))
+ << "Expected full damage rect";
+ }
+ last_swapped_surface_size_ = frame_size;
+ last_swapped_surface_scale_factor_ = frame_device_scale_factor;
+
+ base::SharedMemory* shared_memory_raw_ptr = shared_memory.get();
+ cc::TextureMailbox::ReleaseCallback callback =
+ base::Bind(ReleaseMailbox, Passed(&shared_memory),
+ base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck,
+ AsWeakPtr(), output_surface_id, frame_data->id));
+ current_software_frame_ =
+ cc::TextureMailbox(shared_memory_raw_ptr, frame_size, callback);
+ DCHECK(current_software_frame_.IsSharedMemory());
+ current_frame_size_ = frame_size_in_dip;
+
+ released_front_lock_ = NULL;
+ CheckResizeLock();
+ window_->layer()->SetTextureMailbox(current_software_frame_,
+ frame_device_scale_factor);
+ window_->SchedulePaintInRect(
+ ConvertRectToDIP(frame_device_scale_factor, damage_rect));
+
+ ui::Compositor* compositor = GetCompositor();
+ if (compositor)
+ compositor->SetLatencyInfo(latency_info);
+ if (paint_observer_)
+ paint_observer_->OnUpdateCompositorContent();
+}
+
+void RenderWidgetHostViewAura::SendSoftwareFrameAck(
+ uint32 output_surface_id, unsigned software_frame_id) {
+ cc::CompositorFrameAck ack;
+ ack.last_software_frame_id = software_frame_id;
+ RenderWidgetHostImpl::SendSwapCompositorFrameAck(
+ host_->GetRoutingID(), output_surface_id,
+ host_->GetProcess()->GetID(), ack);
+}
+
+void RenderWidgetHostViewAura::OnSwapCompositorFrame(
+ uint32 output_surface_id,
+ scoped_ptr<cc::CompositorFrame> frame) {
+ if (frame->delegated_frame_data) {
+ SwapDelegatedFrame(output_surface_id,
+ frame->delegated_frame_data.Pass(),
+ frame->metadata.device_scale_factor,
+ frame->metadata.latency_info);
+ return;
+ }
+
+ if (frame->software_frame_data) {
+ SwapSoftwareFrame(output_surface_id,
+ frame->software_frame_data.Pass(),
+ frame->metadata.device_scale_factor,
+ frame->metadata.latency_info);
+ return;
+ }
+
+ if (!frame->gl_frame_data || frame->gl_frame_data->mailbox.IsZero())
+ return;
+
+ BufferPresentedCallback ack_callback = base::Bind(
+ &SendCompositorFrameAck,
+ host_->GetRoutingID(), output_surface_id, host_->GetProcess()->GetID(),
+ frame->gl_frame_data->mailbox, frame->gl_frame_data->size);
+
+ if (!frame->gl_frame_data->sync_point) {
+ LOG(ERROR) << "CompositorFrame without sync point. Skipping frame...";
+ ack_callback.Run(true, scoped_refptr<ui::Texture>());
+ return;
+ }
+
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ factory->WaitSyncPoint(frame->gl_frame_data->sync_point);
+
+ std::string mailbox_name(
+ reinterpret_cast<const char*>(frame->gl_frame_data->mailbox.name),
+ sizeof(frame->gl_frame_data->mailbox.name));
+ BuffersSwapped(frame->gl_frame_data->size,
+ frame->gl_frame_data->sub_buffer_rect,
+ frame->metadata.device_scale_factor,
+ mailbox_name,
+ frame->metadata.latency_info,
+ ack_callback);
+}
+
+#if defined(OS_WIN)
+void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
+ gfx::NativeViewAccessible accessible_parent) {
+ if (GetBrowserAccessibilityManager()) {
+ GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerWin()
+ ->set_parent_iaccessible(accessible_parent);
+ }
+}
+#endif
+
+void RenderWidgetHostViewAura::BuffersSwapped(
+ const gfx::Size& surface_size,
+ const gfx::Rect& damage_rect,
+ float surface_scale_factor,
+ const std::string& mailbox_name,
+ const ui::LatencyInfo& latency_info,
+ const BufferPresentedCallback& ack_callback) {
+ scoped_refptr<ui::Texture> previous_texture(current_surface_);
+ const gfx::Rect surface_rect = gfx::Rect(surface_size);
+
+ if (!SwapBuffersPrepare(surface_rect,
+ surface_scale_factor,
+ damage_rect,
+ mailbox_name,
+ ack_callback)) {
+ return;
+ }
+
+ SkRegion damage(RectToSkIRect(damage_rect));
+ if (!skipped_damage_.isEmpty()) {
+ damage.op(skipped_damage_, SkRegion::kUnion_Op);
+ skipped_damage_.setEmpty();
+ }
+
+ DCHECK(surface_rect.Contains(SkIRectToRect(damage.getBounds())));
+ ui::Texture* current_texture = current_surface_.get();
+
+ const gfx::Size surface_size_in_pixel = surface_size;
+ DLOG_IF(ERROR, previous_texture.get() &&
+ previous_texture->size() != current_texture->size() &&
+ SkIRectToRect(damage.getBounds()) != surface_rect) <<
+ "Expected full damage rect after size change";
+ if (previous_texture.get() && !previous_damage_.isEmpty() &&
+ previous_texture->size() == current_texture->size()) {
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ GLHelper* gl_helper = factory->GetGLHelper();
+ gl_helper->CopySubBufferDamage(
+ current_texture->PrepareTexture(),
+ previous_texture->PrepareTexture(),
+ damage,
+ previous_damage_);
+ }
+ previous_damage_ = damage;
+
+ ui::Compositor* compositor = GetCompositor();
+ if (compositor) {
+ // Co-ordinates come in OpenGL co-ordinate space.
+ // We need to convert to layer space.
+ gfx::Rect rect_to_paint =
+ ConvertRectToDIP(surface_scale_factor,
+ gfx::Rect(damage_rect.x(),
+ surface_size_in_pixel.height() -
+ damage_rect.y() - damage_rect.height(),
+ damage_rect.width(),
+ damage_rect.height()));
+
+ // Damage may not have been DIP aligned, so inflate damage to compensate
+ // for any round-off error.
+ rect_to_paint.Inset(-1, -1);
+ rect_to_paint.Intersect(window_->bounds());
+
+ if (paint_observer_)
+ paint_observer_->OnUpdateCompositorContent();
+ window_->SchedulePaintInRect(rect_to_paint);
+ compositor->SetLatencyInfo(latency_info);
+ }
+
+ SwapBuffersCompleted(ack_callback, previous_texture);
+}
+
+void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
+ const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel,
+ int gpu_host_id) {
+ gfx::Rect damage_rect(params_in_pixel.x,
+ params_in_pixel.y,
+ params_in_pixel.width,
+ params_in_pixel.height);
+ BufferPresentedCallback ack_callback =
+ base::Bind(&AcknowledgeBufferForGpu,
+ params_in_pixel.route_id,
+ gpu_host_id,
+ params_in_pixel.mailbox_name);
+ BuffersSwapped(params_in_pixel.surface_size,
+ damage_rect,
+ params_in_pixel.surface_scale_factor,
+ params_in_pixel.mailbox_name,
+ params_in_pixel.latency_info,
+ ack_callback);
+}
+
+void RenderWidgetHostViewAura::AcceleratedSurfaceSuspend() {
+}
+
+void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() {
+ // This really tells us to release the frontbuffer.
+ if (current_surface_.get()) {
+ ui::Compositor* compositor = GetCompositor();
+ if (compositor) {
+ // We need to wait for a commit to clear to guarantee that all we
+ // will not issue any more GL referencing the previous surface.
+ AddOnCommitCallbackAndDisableLocks(
+ base::Bind(&RenderWidgetHostViewAura::
+ SetSurfaceNotInUseByCompositor,
+ AsWeakPtr(),
+ current_surface_)); // Hold a ref so the texture will not
+ // get deleted until after commit.
+ }
+ current_surface_ = NULL;
+ UpdateExternalTexture();
+ }
+}
+
+bool RenderWidgetHostViewAura::HasAcceleratedSurface(
+ const gfx::Size& desired_size) {
+ // Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
+ // matter what is returned here as GetBackingStore is the only caller of this
+ // method. TODO(jbates) implement this if other Aura code needs it.
+ return false;
+}
+
+void RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor(
+ scoped_refptr<ui::Texture>) {
+}
+
+// static
+void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult(
+ const gfx::Size& dst_size_in_pixel,
+ const base::Callback<void(bool, const SkBitmap&)>& callback,
+ scoped_ptr<cc::CopyOutputResult> result) {
+ if (result->IsEmpty() || result->size().IsEmpty()) {
+ callback.Run(false, SkBitmap());
+ return;
+ }
+
+ if (result->HasTexture()) {
+ PrepareTextureCopyOutputResult(dst_size_in_pixel, callback, result.Pass());
+ return;
+ }
+
+ DCHECK(result->HasBitmap());
+ PrepareBitmapCopyOutputResult(dst_size_in_pixel, callback, result.Pass());
+}
+
+static void CopyFromCompositingSurfaceFinished(
+ const base::Callback<void(bool, const SkBitmap&)>& callback,
+ const cc::TextureMailbox::ReleaseCallback& release_callback,
+ scoped_ptr<SkBitmap> bitmap,
+ scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
+ bool result) {
+ bitmap_pixels_lock.reset();
+ release_callback.Run(0, false);
+ callback.Run(result, *bitmap);
+}
+
+// static
+void RenderWidgetHostViewAura::PrepareTextureCopyOutputResult(
+ const gfx::Size& dst_size_in_pixel,
+ const base::Callback<void(bool, const SkBitmap&)>& callback,
+ scoped_ptr<cc::CopyOutputResult> result) {
+ base::ScopedClosureRunner scoped_callback_runner(
+ base::Bind(callback, false, SkBitmap()));
+
+ DCHECK(result->HasTexture());
+ if (!result->HasTexture())
+ return;
+
+ scoped_ptr<SkBitmap> bitmap(new SkBitmap);
+ bitmap->setConfig(SkBitmap::kARGB_8888_Config,
+ dst_size_in_pixel.width(), dst_size_in_pixel.height());
+ if (!bitmap->allocPixels())
+ return;
+ bitmap->setIsOpaque(true);
+
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ GLHelper* gl_helper = factory->GetGLHelper();
+ if (!gl_helper)
+ return;
+
+ scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
+ new SkAutoLockPixels(*bitmap));
+ uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
+
+ scoped_ptr<cc::TextureMailbox> texture_mailbox = result->TakeTexture();
+ DCHECK(texture_mailbox->IsTexture());
+ if (!texture_mailbox->IsTexture())
+ return;
+
+ scoped_callback_runner.Release();
+
+ gl_helper->CropScaleReadbackAndCleanMailbox(
+ texture_mailbox->name(),
+ texture_mailbox->sync_point(),
+ result->size(),
+ gfx::Rect(result->size()),
+ dst_size_in_pixel,
+ pixels,
+ base::Bind(&CopyFromCompositingSurfaceFinished,
+ callback,
+ texture_mailbox->callback(),
+ base::Passed(&bitmap),
+ base::Passed(&bitmap_pixels_lock)));
+}
+
+// static
+void RenderWidgetHostViewAura::PrepareBitmapCopyOutputResult(
+ const gfx::Size& dst_size_in_pixel,
+ const base::Callback<void(bool, const SkBitmap&)>& callback,
+ scoped_ptr<cc::CopyOutputResult> result) {
+ DCHECK(result->HasBitmap());
+
+ base::ScopedClosureRunner scoped_callback_runner(
+ base::Bind(callback, false, SkBitmap()));
+ if (!result->HasBitmap())
+ return;
+
+ scoped_ptr<SkBitmap> source = result->TakeBitmap();
+ DCHECK(source);
+ if (!source)
+ return;
+
+ scoped_callback_runner.Release();
+
+ SkBitmap bitmap = skia::ImageOperations::Resize(
+ *source,
+ skia::ImageOperations::RESIZE_BEST,
+ dst_size_in_pixel.width(),
+ dst_size_in_pixel.height());
+ callback.Run(true, bitmap);
+}
+
+static void CopyFromCompositingSurfaceFinishedForVideo(
+ const base::Callback<void(bool)>& callback,
+ const cc::TextureMailbox::ReleaseCallback& release_callback,
+ bool result) {
+ release_callback.Run(0, false);
+ callback.Run(result);
+}
+
+// static
+void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo(
+ base::WeakPtr<RenderWidgetHostViewAura> rwhva,
+ scoped_refptr<media::VideoFrame> video_frame,
+ const base::Callback<void(bool)>& callback,
+ scoped_ptr<cc::CopyOutputResult> result) {
+ base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
+
+ if (!rwhva)
+ return;
+
+ if (result->IsEmpty())
+ return;
+ if (result->size().IsEmpty())
+ return;
+
+ // Compute the dest size we want after the letterboxing resize. Make the
+ // coordinates and sizes even because we letterbox in YUV space
+ // (see CopyRGBToVideoFrame). They need to be even for the UV samples to
+ // line up correctly.
+ // The video frame's coded_size() and the result's size() are both physical
+ // pixels.
+ gfx::Rect region_in_frame =
+ media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()),
+ result->size());
+ region_in_frame = gfx::Rect(region_in_frame.x() & ~1,
+ region_in_frame.y() & ~1,
+ region_in_frame.width() & ~1,
+ region_in_frame.height() & ~1);
+ if (region_in_frame.IsEmpty())
+ return;
+
+ // We only handle texture readbacks for now. If the compositor is in software
+ // mode, we could produce a software-backed VideoFrame here as well.
+ if (!result->HasTexture())
+ return;
+
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ GLHelper* gl_helper = factory->GetGLHelper();
+ if (!gl_helper)
+ return;
+
+ scoped_ptr<cc::TextureMailbox> texture_mailbox = result->TakeTexture();
+ DCHECK(texture_mailbox->IsTexture());
+ if (!texture_mailbox->IsTexture())
+ return;
+
+ gfx::Rect result_rect(result->size());
+
+ content::ReadbackYUVInterface* yuv_readback_pipeline =
+ rwhva->yuv_readback_pipeline_.get();
+ if (yuv_readback_pipeline == NULL ||
+ yuv_readback_pipeline->scaler()->SrcSize() != result_rect.size() ||
+ yuv_readback_pipeline->scaler()->SrcSubrect() != result_rect ||
+ yuv_readback_pipeline->scaler()->DstSize() != region_in_frame.size()) {
+ GLHelper::ScalerQuality quality = GLHelper::SCALER_QUALITY_FAST;
+ std::string quality_switch = switches::kTabCaptureDownscaleQuality;
+ // If we're scaling up, we can use the "best" quality.
+ if (result_rect.size().width() < region_in_frame.size().width() &&
+ result_rect.size().height() < region_in_frame.size().height())
+ quality_switch = switches::kTabCaptureUpscaleQuality;
+
+ std::string switch_value =
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(quality_switch);
+ if (switch_value == "fast")
+ quality = GLHelper::SCALER_QUALITY_FAST;
+ else if (switch_value == "good")
+ quality = GLHelper::SCALER_QUALITY_GOOD;
+ else if (switch_value == "best")
+ quality = GLHelper::SCALER_QUALITY_BEST;
+
+ rwhva->yuv_readback_pipeline_.reset(
+ gl_helper->CreateReadbackPipelineYUV(quality,
+ result_rect.size(),
+ result_rect,
+ video_frame->coded_size(),
+ region_in_frame,
+ true,
+ false));
+ yuv_readback_pipeline = rwhva->yuv_readback_pipeline_.get();
+ }
+
+ scoped_callback_runner.Release();
+ base::Callback<void(bool result)> finished_callback = base::Bind(
+ &CopyFromCompositingSurfaceFinishedForVideo,
+ callback,
+ texture_mailbox->callback());
+ yuv_readback_pipeline->ReadbackYUV(
+ texture_mailbox->name(),
+ texture_mailbox->sync_point(),
+ video_frame.get(),
+ finished_callback);
+}
+
+void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) {
+ GetScreenInfoForWindow(results, window_->GetRootWindow() ? window_ : NULL);
+}
+
+gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
+ return window_->GetToplevelWindow()->GetBoundsInScreen();
+}
+
+void RenderWidgetHostViewAura::GestureEventAck(int gesture_event_type) {
+ if (touch_editing_client_)
+ touch_editing_client_->GestureEventAck(gesture_event_type);
+}
+
+void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
+ const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
+ ScopedVector<ui::TouchEvent> events;
+ if (!MakeUITouchEventsFromWebTouchEvents(touch, &events,
+ SCREEN_COORDINATES))
+ return;
+
+ aura::RootWindow* root = window_->GetRootWindow();
+ // |root| is NULL during tests.
+ if (!root)
+ return;
+
+ ui::EventResult result = (ack_result ==
+ INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
+ for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
+ end = events.end(); iter != end; ++iter) {
+ root->ProcessedTouchEvent((*iter), window_, result);
+ }
+}
+
+SmoothScrollGesture* RenderWidgetHostViewAura::CreateSmoothScrollGesture(
+ bool scroll_down,
+ int pixels_to_scroll,
+ int mouse_event_x,
+ int mouse_event_y) {
+ return new TouchSmoothScrollGestureAura(scroll_down,
+ pixels_to_scroll,
+ mouse_event_x,
+ mouse_event_y,
+ window_);
+}
+
+void RenderWidgetHostViewAura::SetHasHorizontalScrollbar(
+ bool has_horizontal_scrollbar) {
+ // Not needed. Mac-only.
+}
+
+void RenderWidgetHostViewAura::SetScrollOffsetPinning(
+ bool is_pinned_to_left, bool is_pinned_to_right) {
+ // Not needed. Mac-only.
+}
+
+void RenderWidgetHostViewAura::OnAccessibilityNotifications(
+ const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+ BrowserAccessibilityManager* manager =
+ GetOrCreateBrowserAccessibilityManager();
+ if (manager)
+ manager->OnAccessibilityNotifications(params);
+}
+
+gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
+ if (shared_surface_handle_.is_null()) {
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ shared_surface_handle_ = factory->CreateSharedSurfaceHandle();
+ factory->AddObserver(this);
+ }
+ return shared_surface_handle_;
+}
+
+bool RenderWidgetHostViewAura::LockMouse() {
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ if (!root_window)
+ return false;
+
+ if (mouse_locked_)
+ return true;
+
+ mouse_locked_ = true;
+ window_->SetCapture();
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(root_window);
+ if (cursor_client) {
+ cursor_client->HideCursor();
+ cursor_client->LockCursor();
+ }
+
+ if (ShouldMoveToCenter()) {
+ synthetic_move_sent_ = true;
+ window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
+ }
+ if (aura::client::GetTooltipClient(root_window))
+ aura::client::GetTooltipClient(root_window)->SetTooltipsEnabled(false);
+ return true;
+}
+
+void RenderWidgetHostViewAura::UnlockMouse() {
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ if (!mouse_locked_ || !root_window)
+ return;
+
+ mouse_locked_ = false;
+
+ window_->ReleaseCapture();
+ window_->MoveCursorTo(unlocked_mouse_position_);
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(root_window);
+ if (cursor_client) {
+ cursor_client->UnlockCursor();
+ cursor_client->ShowCursor();
+ }
+
+ if (aura::client::GetTooltipClient(root_window))
+ aura::client::GetTooltipClient(root_window)->SetTooltipsEnabled(true);
+
+ host_->LostMouseLock();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, ui::TextInputClient implementation:
+void RenderWidgetHostViewAura::SetCompositionText(
+ const ui::CompositionText& composition) {
+ if (!host_)
+ return;
+
+ // ui::CompositionUnderline should be identical to
+ // WebKit::WebCompositionUnderline, so that we can do reinterpret_cast safely.
+ COMPILE_ASSERT(sizeof(ui::CompositionUnderline) ==
+ sizeof(WebKit::WebCompositionUnderline),
+ ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
+
+ // TODO(suzhe): convert both renderer_host and renderer to use
+ // ui::CompositionText.
+ const std::vector<WebKit::WebCompositionUnderline>& underlines =
+ reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>(
+ composition.underlines);
+
+ // TODO(suzhe): due to a bug of webkit, we can't use selection range with
+ // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
+ host_->ImeSetComposition(composition.text, underlines,
+ composition.selection.end(),
+ composition.selection.end());
+
+ has_composition_text_ = !composition.text.empty();
+}
+
+void RenderWidgetHostViewAura::ConfirmCompositionText() {
+ if (host_ && has_composition_text_)
+ host_->ImeConfirmComposition(string16(), ui::Range::InvalidRange(), false);
+ has_composition_text_ = false;
+}
+
+void RenderWidgetHostViewAura::ClearCompositionText() {
+ if (host_ && has_composition_text_)
+ host_->ImeCancelComposition();
+ has_composition_text_ = false;
+}
+
+void RenderWidgetHostViewAura::InsertText(const string16& text) {
+ DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
+ if (host_)
+ host_->ImeConfirmComposition(text, ui::Range::InvalidRange(), false);
+ has_composition_text_ = false;
+}
+
+void RenderWidgetHostViewAura::InsertChar(char16 ch, int flags) {
+ if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
+ popup_child_host_view_->InsertChar(ch, flags);
+ return;
+ }
+
+ if (host_) {
+ double now = ui::EventTimeForNow().InSecondsF();
+ // Send a WebKit::WebInputEvent::Char event to |host_|.
+ NativeWebKeyboardEvent webkit_event(ui::ET_KEY_PRESSED,
+ true /* is_char */,
+ ch,
+ flags,
+ now);
+ host_->ForwardKeyboardEvent(webkit_event);
+ }
+}
+
+gfx::NativeWindow RenderWidgetHostViewAura::GetAttachedWindow() const {
+ return window_;
+}
+
+ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const {
+ return text_input_type_;
+}
+
+bool RenderWidgetHostViewAura::CanComposeInline() const {
+ return can_compose_inline_;
+}
+
+gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(const gfx::Rect& rect) {
+ gfx::Point origin = rect.origin();
+ gfx::Point end = gfx::Point(rect.right(), rect.bottom());
+
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ if (root_window) {
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(root_window);
+ screen_position_client->ConvertPointToScreen(window_, &origin);
+ screen_position_client->ConvertPointToScreen(window_, &end);
+ return gfx::Rect(origin.x(),
+ origin.y(),
+ end.x() - origin.x(),
+ end.y() - origin.y());
+ }
+
+ return rect;
+}
+
+gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
+ const gfx::Rect& rect) {
+ gfx::Point origin = rect.origin();
+ gfx::Point end = gfx::Point(rect.right(), rect.bottom());
+
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ if (root_window) {
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(root_window);
+ screen_position_client->ConvertPointFromScreen(window_, &origin);
+ screen_position_client->ConvertPointFromScreen(window_, &end);
+ return gfx::Rect(origin.x(),
+ origin.y(),
+ end.x() - origin.x(),
+ end.y() - origin.y());
+ }
+
+ return rect;
+}
+
+gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() {
+ const gfx::Rect rect =
+ gfx::UnionRects(selection_anchor_rect_, selection_focus_rect_);
+ return ConvertRectToScreen(rect);
+}
+
+bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(uint32 index,
+ gfx::Rect* rect) {
+ DCHECK(rect);
+ if (index >= composition_character_bounds_.size())
+ return false;
+ *rect = ConvertRectToScreen(composition_character_bounds_[index]);
+ return true;
+}
+
+bool RenderWidgetHostViewAura::HasCompositionText() {
+ return has_composition_text_;
+}
+
+bool RenderWidgetHostViewAura::GetTextRange(ui::Range* range) {
+ range->set_start(selection_text_offset_);
+ range->set_end(selection_text_offset_ + selection_text_.length());
+ return true;
+}
+
+bool RenderWidgetHostViewAura::GetCompositionTextRange(ui::Range* range) {
+ // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool RenderWidgetHostViewAura::GetSelectionRange(ui::Range* range) {
+ range->set_start(selection_range_.start());
+ range->set_end(selection_range_.end());
+ return true;
+}
+
+bool RenderWidgetHostViewAura::SetSelectionRange(const ui::Range& range) {
+ // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool RenderWidgetHostViewAura::DeleteRange(const ui::Range& range) {
+ // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool RenderWidgetHostViewAura::GetTextFromRange(
+ const ui::Range& range,
+ string16* text) {
+ ui::Range selection_text_range(selection_text_offset_,
+ selection_text_offset_ + selection_text_.length());
+
+ if (!selection_text_range.Contains(range)) {
+ text->clear();
+ return false;
+ }
+ if (selection_text_range.EqualsIgnoringDirection(range)) {
+ // Avoid calling substr whose performance is low.
+ *text = selection_text_;
+ } else {
+ *text = selection_text_.substr(
+ range.GetMin() - selection_text_offset_,
+ range.length());
+ }
+ return true;
+}
+
+void RenderWidgetHostViewAura::OnInputMethodChanged() {
+ if (!host_)
+ return;
+
+ if (GetInputMethod())
+ host_->SetInputMethodActive(GetInputMethod()->IsActive());
+
+ // TODO(suzhe): implement the newly added “locale” property of HTML DOM
+ // TextEvent.
+}
+
+bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
+ base::i18n::TextDirection direction) {
+ if (!host_)
+ return false;
+ host_->UpdateTextDirection(
+ direction == base::i18n::RIGHT_TO_LEFT ?
+ WebKit::WebTextDirectionRightToLeft :
+ WebKit::WebTextDirectionLeftToRight);
+ host_->NotifyTextDirection();
+ return true;
+}
+
+void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
+ size_t before, size_t after) {
+ if (host_)
+ host_->ExtendSelectionAndDelete(before, after);
+}
+
+void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
+ gfx::Rect intersected_rect(
+ gfx::IntersectRects(rect, window_->GetBoundsInScreen()));
+
+ if (intersected_rect.IsEmpty())
+ return;
+
+ host_->ScrollFocusedEditableNodeIntoRect(
+ ConvertRectFromScreen(intersected_rect));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, gfx::DisplayObserver implementation:
+
+void RenderWidgetHostViewAura::OnDisplayBoundsChanged(
+ const gfx::Display& display) {
+ gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
+ if (display.id() == screen->GetDisplayNearestWindow(window_).id()) {
+ UpdateScreenInfo(window_);
+ }
+}
+
+void RenderWidgetHostViewAura::OnDisplayAdded(
+ const gfx::Display& new_display) {
+}
+
+void RenderWidgetHostViewAura::OnDisplayRemoved(
+ const gfx::Display& old_display) {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, aura::WindowDelegate implementation:
+
+gfx::Size RenderWidgetHostViewAura::GetMinimumSize() const {
+ return gfx::Size();
+}
+
+gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const {
+ return gfx::Size();
+}
+
+void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) {
+ // We care about this only in fullscreen mode, where there is no
+ // WebContentsViewAura. We are sized via SetSize() or SetBounds() by
+ // WebContentsViewAura in other cases.
+ if (is_fullscreen_)
+ SetSize(new_bounds.size());
+}
+
+gfx::NativeCursor RenderWidgetHostViewAura::GetCursor(const gfx::Point& point) {
+ if (mouse_locked_)
+ return ui::kCursorNone;
+ return current_cursor_.GetNativeCursor();
+}
+
+int RenderWidgetHostViewAura::GetNonClientComponent(
+ const gfx::Point& point) const {
+ return HTCLIENT;
+}
+
+bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
+ aura::Window* child,
+ const gfx::Point& location) {
+ return true;
+}
+
+bool RenderWidgetHostViewAura::CanFocus() {
+ return popup_type_ == WebKit::WebPopupTypeNone;
+}
+
+void RenderWidgetHostViewAura::OnCaptureLost() {
+ host_->LostCapture();
+ if (touch_editing_client_)
+ touch_editing_client_->EndTouchEditing();
+}
+
+void RenderWidgetHostViewAura::OnPaint(gfx::Canvas* canvas) {
+ bool has_backing_store = !!host_->GetBackingStore(false);
+ if (has_backing_store) {
+ paint_canvas_ = canvas;
+ BackingStoreAura* backing_store = static_cast<BackingStoreAura*>(
+ host_->GetBackingStore(true));
+ paint_canvas_ = NULL;
+ backing_store->SkiaShowRect(gfx::Point(), canvas);
+
+ if (paint_observer_)
+ paint_observer_->OnPaintComplete();
+ ui::Compositor* compositor = GetCompositor();
+ if (compositor) {
+ compositor->SetLatencyInfo(software_latency_info_);
+ software_latency_info_.Clear();
+ }
+ } else {
+ // For non-opaque windows, we don't draw anything, since we depend on the
+ // canvas coming from the compositor to already be initialized as
+ // transparent.
+ if (window_->layer()->fills_bounds_opaquely())
+ canvas->DrawColor(SK_ColorWHITE);
+ }
+}
+
+void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
+ float device_scale_factor) {
+ if (!host_)
+ return;
+
+ BackingStoreAura* backing_store = static_cast<BackingStoreAura*>(
+ host_->GetBackingStore(false));
+ if (backing_store) // NULL in hardware path.
+ backing_store->ScaleFactorChanged(device_scale_factor);
+
+ UpdateScreenInfo(window_);
+ DCHECK_EQ(current_device_scale_factor_, device_scale_factor);
+ current_cursor_.SetDeviceScaleFactor(device_scale_factor);
+}
+
+void RenderWidgetHostViewAura::OnWindowDestroying() {
+#if defined(OS_WIN)
+ HWND parent = NULL;
+ // If the tab was hidden and it's closed, host_->is_hidden would have been
+ // reset to false in RenderWidgetHostImpl::RendererExited.
+ if (!window_->GetRootWindow() || host_->is_hidden()) {
+ parent = ui::GetHiddenWindow();
+ } else {
+ parent = window_->GetRootWindow()->GetAcceleratedWidget();
+ }
+ LPARAM lparam = reinterpret_cast<LPARAM>(this);
+ EnumChildWindows(parent, WindowDestroyingCallback, lparam);
+#endif
+}
+
+void RenderWidgetHostViewAura::OnWindowDestroyed() {
+ host_->ViewDestroyed();
+ delete this;
+}
+
+void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible) {
+}
+
+bool RenderWidgetHostViewAura::HasHitTestMask() const {
+ return false;
+}
+
+void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
+}
+
+scoped_refptr<ui::Texture> RenderWidgetHostViewAura::CopyTexture() {
+ if (!host_->is_accelerated_compositing_active())
+ return scoped_refptr<ui::Texture>();
+
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ GLHelper* gl_helper = factory->GetGLHelper();
+ if (!gl_helper)
+ return scoped_refptr<ui::Texture>();
+
+ if (!current_surface_.get())
+ return scoped_refptr<ui::Texture>();
+
+ WebKit::WebGLId texture_id =
+ gl_helper->CopyTexture(current_surface_->PrepareTexture(),
+ current_surface_->size());
+ if (!texture_id)
+ return scoped_refptr<ui::Texture>();
+
+ return scoped_refptr<ui::Texture>(
+ factory->CreateOwnedTexture(
+ current_surface_->size(),
+ current_surface_->device_scale_factor(), texture_id));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, ui::EventHandler implementation:
+
+void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
+ TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent");
+ if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
+ return;
+
+ if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
+ popup_child_host_view_->OnKeyEvent(event);
+ if (event->handled())
+ return;
+ }
+
+ // We need to handle the Escape key for Pepper Flash.
+ if (is_fullscreen_ && event->key_code() == ui::VKEY_ESCAPE) {
+ // Focus the window we were created from.
+ if (host_tracker_.get() && !host_tracker_->windows().empty()) {
+ aura::Window* host = *(host_tracker_->windows().begin());
+ aura::client::FocusClient* client = aura::client::GetFocusClient(host);
+ if (client) {
+ // Calling host->Focus() may delete |this|. We create a local
+ // observer for that. In that case we exit without further
+ // access to any members.
+ aura::WindowDestructionObserver destruction_observer(window_);
+ host->Focus();
+ if (destruction_observer.destroyed()) {
+ event->SetHandled();
+ return;
+ }
+ }
+ }
+ if (!in_shutdown_) {
+ in_shutdown_ = true;
+ host_->Shutdown();
+ }
+ } else {
+ // We don't have to communicate with an input method here.
+ if (!event->HasNativeEvent()) {
+ NativeWebKeyboardEvent webkit_event(
+ event->type(),
+ event->is_char(),
+ event->is_char() ? event->GetCharacter() : event->key_code(),
+ event->flags(),
+ ui::EventTimeForNow().InSecondsF());
+ host_->ForwardKeyboardEvent(webkit_event);
+ } else {
+ NativeWebKeyboardEvent webkit_event(event);
+ host_->ForwardKeyboardEvent(webkit_event);
+ }
+ }
+ event->SetHandled();
+}
+
+void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
+ TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
+
+ if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
+ return;
+
+ if (mouse_locked_) {
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(window_->GetRootWindow());
+ DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
+
+ if (event->type() == ui::ET_MOUSEWHEEL) {
+ WebKit::WebMouseWheelEvent mouse_wheel_event =
+ MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
+ if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
+ host_->ForwardWheelEvent(mouse_wheel_event);
+ return;
+ }
+
+ WebKit::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
+ gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
+
+ bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED ||
+ event->type() == ui::ET_MOUSE_DRAGGED) &&
+ mouse_event.x == center.x() && mouse_event.y == center.y();
+
+ ModifyEventMovementAndCoords(&mouse_event);
+
+ bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
+ if (should_not_forward) {
+ synthetic_move_sent_ = false;
+ } else {
+ // Check if the mouse has reached the border and needs to be centered.
+ if (ShouldMoveToCenter()) {
+ synthetic_move_sent_ = true;
+ window_->MoveCursorTo(center);
+ }
+ // Forward event to renderer.
+ if (CanRendererHandleEvent(event) &&
+ !(event->flags() & ui::EF_FROM_TOUCH))
+ host_->ForwardMouseEvent(mouse_event);
+ }
+ return;
+ }
+
+ // As the overscroll is handled during scroll events from the trackpad, the
+ // RWHVA window is transformed by the overscroll controller. This transform
+ // triggers a synthetic mouse-move event to be generated (by the aura
+ // RootWindow). But this event interferes with the overscroll gesture. So,
+ // ignore such synthetic mouse-move events if an overscroll gesture is in
+ // progress.
+ if (host_->overscroll_controller() &&
+ host_->overscroll_controller()->overscroll_mode() != OVERSCROLL_NONE &&
+ event->flags() & ui::EF_IS_SYNTHESIZED &&
+ (event->type() == ui::ET_MOUSE_ENTERED ||
+ event->type() == ui::ET_MOUSE_EXITED ||
+ event->type() == ui::ET_MOUSE_MOVED)) {
+ event->StopPropagation();
+ return;
+ }
+
+ if (event->type() == ui::ET_MOUSEWHEEL) {
+#if defined(OS_WIN)
+ // We get mouse wheel/scroll messages even if we are not in the foreground.
+ // So here we check if we have any owned popup windows in the foreground and
+ // dismiss them.
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ if (root_window) {
+ HWND parent = root_window->GetAcceleratedWidget();
+ HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
+ EnumThreadWindows(GetCurrentThreadId(),
+ DismissOwnedPopups,
+ reinterpret_cast<LPARAM>(toplevel_hwnd));
+ }
+#endif
+ WebKit::WebMouseWheelEvent mouse_wheel_event =
+ MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
+ if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
+ host_->ForwardWheelEvent(mouse_wheel_event);
+ } else if (CanRendererHandleEvent(event) &&
+ !(event->flags() & ui::EF_FROM_TOUCH)) {
+ WebKit::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
+ ModifyEventMovementAndCoords(&mouse_event);
+ host_->ForwardMouseEvent(mouse_event);
+ }
+
+ switch (event->type()) {
+ case ui::ET_MOUSE_PRESSED:
+ window_->SetCapture();
+ // Confirm existing composition text on mouse click events, to make sure
+ // the input caret won't be moved with an ongoing composition text.
+ FinishImeCompositionSession();
+ break;
+ case ui::ET_MOUSE_RELEASED:
+ window_->ReleaseCapture();
+ break;
+ default:
+ break;
+ }
+
+ // Needed to propagate mouse event to native_tab_contents_view_aura.
+ // TODO(pkotwicz): Find a better way of doing this.
+ // In fullscreen mode which is typically used by flash, don't forward
+ // the mouse events to the parent. The renderer and the plugin process
+ // handle these events.
+ if (!is_fullscreen_ && window_->parent()->delegate() &&
+ !(event->flags() & ui::EF_FROM_TOUCH))
+ window_->parent()->delegate()->OnMouseEvent(event);
+
+ if (!IsXButtonUpEvent(event))
+ event->SetHandled();
+}
+
+void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
+ TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
+ if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
+ return;
+
+ if (event->type() == ui::ET_SCROLL) {
+ if (event->finger_count() != 2)
+ return;
+ WebKit::WebGestureEvent gesture_event =
+ MakeWebGestureEventFlingCancel();
+ host_->ForwardGestureEvent(gesture_event);
+ WebKit::WebMouseWheelEvent mouse_wheel_event =
+ MakeWebMouseWheelEvent(event);
+ host_->ForwardWheelEvent(mouse_wheel_event);
+ RecordAction(UserMetricsAction("TrackpadScroll"));
+ } else if (event->type() == ui::ET_SCROLL_FLING_START ||
+ event->type() == ui::ET_SCROLL_FLING_CANCEL) {
+ WebKit::WebGestureEvent gesture_event =
+ MakeWebGestureEvent(event);
+ host_->ForwardGestureEvent(gesture_event);
+ if (event->type() == ui::ET_SCROLL_FLING_START)
+ RecordAction(UserMetricsAction("TrackpadScrollFling"));
+ }
+
+ event->SetHandled();
+}
+
+void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
+ TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent");
+ if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
+ return;
+
+ // Update the touch event first.
+ WebKit::WebTouchPoint* point = UpdateWebTouchEventFromUIEvent(*event,
+ &touch_event_);
+
+ // Forward the touch event only if a touch point was updated, and there's a
+ // touch-event handler in the page, and no other touch-event is in the queue.
+ // It is important to always consume the event if there is a touch-event
+ // handler in the page, or some touch-event is already in the queue, even if
+ // no point has been updated, to make sure that this event does not get
+ // processed by the gesture recognizer before the events in the queue.
+ if (host_->ShouldForwardTouchEvent())
+ event->StopPropagation();
+
+ if (point) {
+ if (host_->ShouldForwardTouchEvent())
+ host_->ForwardTouchEventWithLatencyInfo(touch_event_, *event->latency());
+ UpdateWebTouchEventAfterDispatch(&touch_event_, point);
+ }
+}
+
+void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
+ TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent");
+ // Pinch gestures are currently disabled by default. See crbug.com/128477.
+ if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN ||
+ event->type() == ui::ET_GESTURE_PINCH_UPDATE ||
+ event->type() == ui::ET_GESTURE_PINCH_END) && !ShouldSendPinchGesture()) {
+ event->SetHandled();
+ return;
+ }
+
+ if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
+ return;
+
+ RenderViewHostDelegate* delegate = NULL;
+ if (popup_type_ == WebKit::WebPopupTypeNone && !is_fullscreen_)
+ delegate = RenderViewHost::From(host_)->GetDelegate();
+
+ if (delegate && event->type() == ui::ET_GESTURE_BEGIN &&
+ event->details().touch_points() == 1) {
+ delegate->HandleGestureBegin();
+ }
+
+ WebKit::WebGestureEvent gesture = MakeWebGestureEvent(event);
+ if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
+ // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
+ // event to stop any in-progress flings.
+ WebKit::WebGestureEvent fling_cancel = gesture;
+ fling_cancel.type = WebKit::WebInputEvent::GestureFlingCancel;
+ fling_cancel.sourceDevice = WebKit::WebGestureEvent::Touchscreen;
+ host_->ForwardGestureEvent(fling_cancel);
+ }
+
+ if (gesture.type != WebKit::WebInputEvent::Undefined) {
+ host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
+
+ if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
+ event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
+ event->type() == ui::ET_GESTURE_SCROLL_END) {
+ RecordAction(UserMetricsAction("TouchscreenScroll"));
+ } else if (event->type() == ui::ET_SCROLL_FLING_START) {
+ RecordAction(UserMetricsAction("TouchscreenScrollFling"));
+ }
+ }
+
+ if (delegate && event->type() == ui::ET_GESTURE_END &&
+ event->details().touch_points() == 1) {
+ delegate->HandleGestureEnd();
+ }
+
+ // If a gesture is not processed by the webpage, then WebKit processes it
+ // (e.g. generates synthetic mouse events).
+ event->SetHandled();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation:
+
+bool RenderWidgetHostViewAura::ShouldActivate() const {
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ if (!root_window)
+ return true;
+ const ui::Event* event = root_window->current_event();
+ if (!event)
+ return true;
+ return is_fullscreen_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura,
+// aura::client::ActivationChangeObserver implementation:
+
+void RenderWidgetHostViewAura::OnWindowActivated(aura::Window* gained_active,
+ aura::Window* lost_active) {
+ DCHECK(window_ == gained_active || window_ == lost_active);
+ if (window_ == gained_active) {
+ const ui::Event* event = window_->GetRootWindow()->current_event();
+ if (event && PointerEventActivates(*event))
+ host_->OnPointerEventActivate();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation:
+
+void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible) {
+ NotifyRendererOfCursorVisibilityState(is_visible);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation:
+
+void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
+ aura::Window* lost_focus) {
+ DCHECK(window_ == gained_focus || window_ == lost_focus);
+ if (window_ == gained_focus) {
+ // We need to honor input bypass if the associated tab is does not want
+ // input. This gives the current focused window a chance to be the text
+ // input client and handle events.
+ if (host_->ignore_input_events())
+ return;
+
+ host_->GotFocus();
+ host_->SetActive(true);
+
+ ui::InputMethod* input_method = GetInputMethod();
+ if (input_method) {
+ // Ask the system-wide IME to send all TextInputClient messages to |this|
+ // object.
+ input_method->SetFocusedTextInputClient(this);
+ host_->SetInputMethodActive(input_method->IsActive());
+
+ // Often the application can set focus to the view in response to a key
+ // down. However the following char event shouldn't be sent to the web
+ // page.
+ host_->SuppressNextCharEvents();
+ } else {
+ host_->SetInputMethodActive(false);
+ }
+ } else if (window_ == lost_focus) {
+ host_->SetActive(false);
+ host_->Blur();
+
+ DetachFromInputMethod();
+ host_->SetInputMethodActive(false);
+
+ if (touch_editing_client_)
+ touch_editing_client_->EndTouchEditing();
+
+ // If we lose the focus while fullscreen, close the window; Pepper Flash
+ // won't do it for us (unlike NPAPI Flash). However, we do not close the
+ // window if we lose the focus to a window on another display.
+ gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
+ bool focusing_other_display =
+ gained_focus && screen->GetNumDisplays() > 1 &&
+ (screen->GetDisplayNearestWindow(window_).id() !=
+ screen->GetDisplayNearestWindow(gained_focus).id());
+ if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) {
+ in_shutdown_ = true;
+ host_->Shutdown();
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, aura::RootWindowObserver implementation:
+
+void RenderWidgetHostViewAura::OnRootWindowHostMoved(
+ const aura::RootWindow* root,
+ const gfx::Point& new_origin) {
+ UpdateScreenInfo(window_);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, ui::CompositorObserver implementation:
+
+void RenderWidgetHostViewAura::OnCompositingDidCommit(
+ ui::Compositor* compositor) {
+ if (can_lock_compositor_ == NO_PENDING_COMMIT) {
+ can_lock_compositor_ = YES;
+ if (resize_lock_.get() && resize_lock_->GrabDeferredLock())
+ can_lock_compositor_ = YES_DID_LOCK;
+ }
+ RunOnCommitCallbacks();
+ if (resize_lock_ && resize_lock_->expected_size() == current_frame_size_) {
+ resize_lock_.reset();
+ host_->WasResized();
+ // We may have had a resize while we had the lock (e.g. if the lock expired,
+ // or if the UI still gave us some resizes), so make sure we grab a new lock
+ // if necessary.
+ MaybeCreateResizeLock();
+ }
+}
+
+void RenderWidgetHostViewAura::OnCompositingStarted(
+ ui::Compositor* compositor, base::TimeTicks start_time) {
+ last_draw_ended_ = start_time;
+}
+
+void RenderWidgetHostViewAura::OnCompositingEnded(
+ ui::Compositor* compositor) {
+ if (paint_observer_)
+ paint_observer_->OnCompositingComplete();
+}
+
+void RenderWidgetHostViewAura::OnCompositingAborted(
+ ui::Compositor* compositor) {
+}
+
+void RenderWidgetHostViewAura::OnCompositingLockStateChanged(
+ ui::Compositor* compositor) {
+ // A compositor lock that is part of a resize lock timed out. We
+ // should display a renderer frame.
+ if (!compositor->IsLocked() && can_lock_compositor_ == YES_DID_LOCK) {
+ can_lock_compositor_ = NO_PENDING_RENDERER_FRAME;
+ }
+}
+
+void RenderWidgetHostViewAura::OnUpdateVSyncParameters(
+ ui::Compositor* compositor,
+ base::TimeTicks timebase,
+ base::TimeDelta interval) {
+ if (IsShowing() && !last_draw_ended_.is_null())
+ host_->UpdateVSyncParameters(last_draw_ended_, interval);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, BrowserAccessibilityDelegate implementation:
+
+void RenderWidgetHostViewAura::SetAccessibilityFocus(int acc_obj_id) {
+ if (!host_)
+ return;
+
+ host_->AccessibilitySetFocus(acc_obj_id);
+}
+
+void RenderWidgetHostViewAura::AccessibilityDoDefaultAction(int acc_obj_id) {
+ if (!host_)
+ return;
+
+ host_->AccessibilityDoDefaultAction(acc_obj_id);
+}
+
+void RenderWidgetHostViewAura::AccessibilityScrollToMakeVisible(
+ int acc_obj_id, gfx::Rect subfocus) {
+ if (!host_)
+ return;
+
+ host_->AccessibilityScrollToMakeVisible(acc_obj_id, subfocus);
+}
+
+void RenderWidgetHostViewAura::AccessibilityScrollToPoint(
+ int acc_obj_id, gfx::Point point) {
+ if (!host_)
+ return;
+
+ host_->AccessibilityScrollToPoint(acc_obj_id, point);
+}
+
+void RenderWidgetHostViewAura::AccessibilitySetTextSelection(
+ int acc_obj_id, int start_offset, int end_offset) {
+ if (!host_)
+ return;
+
+ host_->AccessibilitySetTextSelection(
+ acc_obj_id, start_offset, end_offset);
+}
+
+gfx::Point RenderWidgetHostViewAura::GetLastTouchEventLocation() const {
+ // Only needed for Win 8 non-aura.
+ return gfx::Point();
+}
+
+void RenderWidgetHostViewAura::FatalAccessibilityTreeError() {
+ host_->FatalAccessibilityTreeError();
+ SetBrowserAccessibilityManager(NULL);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, ImageTransportFactoryObserver implementation:
+
+void RenderWidgetHostViewAura::OnLostResources() {
+ current_surface_ = NULL;
+ UpdateExternalTexture();
+
+ // Make sure all ImageTransportClients are deleted now that the context those
+ // are using is becoming invalid. This sends pending ACKs and needs to happen
+ // after calling UpdateExternalTexture() which syncs with the impl thread.
+ RunOnCommitCallbacks();
+
+ DCHECK(!shared_surface_handle_.is_null());
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ factory->DestroySharedSurfaceHandle(shared_surface_handle_);
+ shared_surface_handle_ = factory->CreateSharedSurfaceHandle();
+ host_->CompositingSurfaceUpdated();
+ host_->ScheduleComposite();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, private:
+
+RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
+ if (paint_observer_)
+ paint_observer_->OnViewDestroyed();
+ if (touch_editing_client_)
+ touch_editing_client_->OnViewDestroyed();
+ if (!shared_surface_handle_.is_null()) {
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ factory->DestroySharedSurfaceHandle(shared_surface_handle_);
+ factory->RemoveObserver(this);
+ }
+ window_observer_.reset();
+#if defined(OS_WIN)
+ transient_observer_.reset();
+#endif
+ if (window_->GetRootWindow())
+ window_->GetRootWindow()->RemoveRootWindowObserver(this);
+ UnlockMouse();
+ if (popup_type_ != WebKit::WebPopupTypeNone && popup_parent_host_view_) {
+ DCHECK(popup_parent_host_view_->popup_child_host_view_ == NULL ||
+ popup_parent_host_view_->popup_child_host_view_ == this);
+ popup_parent_host_view_->popup_child_host_view_ = NULL;
+ }
+ if (popup_child_host_view_) {
+ DCHECK(popup_child_host_view_->popup_parent_host_view_ == NULL ||
+ popup_child_host_view_->popup_parent_host_view_ == this);
+ popup_child_host_view_->popup_parent_host_view_ = NULL;
+ }
+ aura::client::SetTooltipText(window_, NULL);
+ gfx::Screen::GetScreenFor(window_)->RemoveObserver(this);
+
+ // This call is usually no-op since |this| object is already removed from the
+ // Aura root window and we don't have a way to get an input method object
+ // associated with the window, but just in case.
+ DetachFromInputMethod();
+}
+
+void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
+ const gfx::Point screen_point =
+ gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ if (!root_window)
+ return;
+
+ gfx::Rect screen_rect = GetViewBounds();
+ gfx::Point local_point = screen_point;
+ local_point.Offset(-screen_rect.x(), -screen_rect.y());
+
+ if (root_window->GetEventHandlerForPoint(local_point) != window_)
+ return;
+
+ gfx::NativeCursor cursor = current_cursor_.GetNativeCursor();
+ // Do not show loading cursor when the cursor is currently hidden.
+ if (is_loading_ && cursor != ui::kCursorNone)
+ cursor = ui::kCursorPointer;
+
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(root_window);
+ if (cursor_client) {
+ cursor_client->SetCursor(cursor);
+ }
+}
+
+ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ if (!root_window)
+ return NULL;
+ return root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
+}
+
+bool RenderWidgetHostViewAura::NeedsInputGrab() {
+ return popup_type_ == WebKit::WebPopupTypeSelect;
+}
+
+void RenderWidgetHostViewAura::FinishImeCompositionSession() {
+ if (!has_composition_text_)
+ return;
+ if (host_)
+ host_->ImeConfirmComposition(string16(), ui::Range::InvalidRange(), false);
+ ImeCancelComposition();
+}
+
+void RenderWidgetHostViewAura::ModifyEventMovementAndCoords(
+ WebKit::WebMouseEvent* event) {
+ // If the mouse has just entered, we must report zero movementX/Y. Hence we
+ // reset any global_mouse_position set previously.
+ if (event->type == WebKit::WebInputEvent::MouseEnter ||
+ event->type == WebKit::WebInputEvent::MouseLeave)
+ global_mouse_position_.SetPoint(event->globalX, event->globalY);
+
+ // Movement is computed by taking the difference of the new cursor position
+ // and the previous. Under mouse lock the cursor will be warped back to the
+ // center so that we are not limited by clipping boundaries.
+ // We do not measure movement as the delta from cursor to center because
+ // we may receive more mouse movement events before our warp has taken
+ // effect.
+ event->movementX = event->globalX - global_mouse_position_.x();
+ event->movementY = event->globalY - global_mouse_position_.y();
+
+ global_mouse_position_.SetPoint(event->globalX, event->globalY);
+
+ // Under mouse lock, coordinates of mouse are locked to what they were when
+ // mouse lock was entered.
+ if (mouse_locked_) {
+ event->x = unlocked_mouse_position_.x();
+ event->y = unlocked_mouse_position_.y();
+ event->windowX = unlocked_mouse_position_.x();
+ event->windowY = unlocked_mouse_position_.y();
+ event->globalX = unlocked_global_mouse_position_.x();
+ event->globalY = unlocked_global_mouse_position_.y();
+ } else {
+ unlocked_mouse_position_.SetPoint(event->windowX, event->windowY);
+ unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY);
+ }
+}
+
+void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
+ bool is_visible) {
+ if (host_->is_hidden() ||
+ (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) ||
+ (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible))
+ return;
+
+ cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE;
+ host_->SendCursorVisibilityState(is_visible);
+}
+
+void RenderWidgetHostViewAura::SchedulePaintIfNotInClip(
+ const gfx::Rect& rect,
+ const gfx::Rect& clip) {
+ if (!clip.IsEmpty()) {
+ gfx::Rect to_paint = gfx::SubtractRects(rect, clip);
+ if (!to_paint.IsEmpty())
+ window_->SchedulePaintInRect(to_paint);
+ } else {
+ window_->SchedulePaintInRect(rect);
+ }
+}
+
+bool RenderWidgetHostViewAura::ShouldMoveToCenter() {
+ gfx::Rect rect = window_->bounds();
+ rect = ConvertRectToScreen(rect);
+ int border_x = rect.width() * kMouseLockBorderPercentage / 100;
+ int border_y = rect.height() * kMouseLockBorderPercentage / 100;
+
+ return global_mouse_position_.x() < rect.x() + border_x ||
+ global_mouse_position_.x() > rect.right() - border_x ||
+ global_mouse_position_.y() < rect.y() + border_y ||
+ global_mouse_position_.y() > rect.bottom() - border_y;
+}
+
+void RenderWidgetHostViewAura::RunOnCommitCallbacks() {
+ for (std::vector<base::Closure>::const_iterator
+ it = on_compositing_did_commit_callbacks_.begin();
+ it != on_compositing_did_commit_callbacks_.end(); ++it) {
+ it->Run();
+ }
+ on_compositing_did_commit_callbacks_.clear();
+}
+
+void RenderWidgetHostViewAura::AddOnCommitCallbackAndDisableLocks(
+ const base::Closure& callback) {
+ ui::Compositor* compositor = GetCompositor();
+ DCHECK(compositor);
+
+ if (!compositor->HasObserver(this))
+ compositor->AddObserver(this);
+
+ can_lock_compositor_ = NO_PENDING_COMMIT;
+ on_compositing_did_commit_callbacks_.push_back(callback);
+}
+
+void RenderWidgetHostViewAura::AddedToRootWindow() {
+ window_->GetRootWindow()->AddRootWindowObserver(this);
+ host_->ParentChanged(GetNativeViewId());
+ UpdateScreenInfo(window_);
+ if (popup_type_ != WebKit::WebPopupTypeNone)
+ event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
+
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(window_->GetRootWindow());
+ if (cursor_client) {
+ cursor_client->AddObserver(this);
+ NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
+ }
+ UpdateExternalTexture();
+}
+
+void RenderWidgetHostViewAura::RemovingFromRootWindow() {
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(window_->GetRootWindow());
+ if (cursor_client)
+ cursor_client->RemoveObserver(this);
+
+ event_filter_for_popup_exit_.reset();
+ window_->GetRootWindow()->RemoveRootWindowObserver(this);
+ host_->ParentChanged(0);
+ ui::Compositor* compositor = GetCompositor();
+ // We can't get notification for commits after this point, which would
+ // guarantee that the compositor isn't using an old texture any more, so
+ // instead we force the texture to NULL which synchronizes with the compositor
+ // thread, and makes it safe to run the callback.
+ window_->layer()->SetExternalTexture(NULL);
+ RunOnCommitCallbacks();
+ resize_lock_.reset();
+ host_->WasResized();
+ if (compositor && compositor->HasObserver(this))
+ compositor->RemoveObserver(this);
+}
+
+ui::Compositor* RenderWidgetHostViewAura::GetCompositor() {
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ return root_window ? root_window->compositor() : NULL;
+}
+
+void RenderWidgetHostViewAura::DetachFromInputMethod() {
+ ui::InputMethod* input_method = GetInputMethod();
+ if (input_method && input_method->GetTextInputClient() == this)
+ input_method->SetFocusedTextInputClient(NULL);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostView, public:
+
+// static
+RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
+ RenderWidgetHost* widget) {
+ return new RenderWidgetHostViewAura(widget);
+}
+
+// static
+void RenderWidgetHostViewPort::GetDefaultScreenInfo(WebScreenInfo* results) {
+ GetScreenInfoForWindow(results, NULL);
+}
+
+} // namespace content
« no previous file with comments | « content/browser/renderer_host/render_widget_host_view_aura.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698