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>(¶ms); |
- 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>(¶ms); |
+ 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 |