1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
7 #include "base/auto_reset.h"
8 #include "base/basictypes.h"
10 #include "base/callback_helpers.h"
11 #include "base/command_line.h"
12 #include "base/debug/trace_event.h"
13 #include "base/logging.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "cc/layers/delegated_frame_provider.h"
17 #include "cc/output/compositor_frame.h"
18 #include "cc/output/compositor_frame_ack.h"
19 #include "cc/output/copy_output_request.h"
20 #include "cc/output/copy_output_result.h"
21 #include "cc/resources/texture_mailbox.h"
22 #include "cc/trees/layer_tree_settings.h"
23 #include "content/browser/accessibility/browser_accessibility_manager.h"
24 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
25 #include "content/browser/frame_host/frame_tree.h"
26 #include "content/browser/frame_host/frame_tree_node.h"
27 #include "content/browser/frame_host/render_frame_host_impl.h"
28 #include "content/browser/gpu/compositor_util.h"
29 #include "content/browser/renderer_host/backing_store_aura.h"
30 #include "content/browser/renderer_host/compositor_resize_lock_aura.h"
31 #include "content/browser/renderer_host/dip_util.h"
32 #include "content/browser/renderer_host/input/synthetic_gesture_target_aura.h"
33 #include "content/browser/renderer_host/overscroll_controller.h"
34 #include "content/browser/renderer_host/render_view_host_delegate.h"
35 #include "content/browser/renderer_host/render_view_host_impl.h"
36 #include "content/browser/renderer_host/render_widget_host_impl.h"
37 #include "content/browser/renderer_host/ui_events_helper.h"
38 #include "content/browser/renderer_host/web_input_event_aura.h"
39 #include "content/common/gpu/client/gl_helper.h"
40 #include "content/common/gpu/gpu_messages.h"
41 #include "content/common/view_messages.h"
42 #include "content/port/browser/render_widget_host_view_frame_subscriber.h"
43 #include "content/port/browser/render_widget_host_view_port.h"
44 #include "content/public/browser/content_browser_client.h"
45 #include "content/public/browser/render_process_host.h"
46 #include "content/public/browser/render_view_host.h"
47 #include "content/public/browser/user_metrics.h"
48 #include "content/public/common/content_switches.h"
49 #include "media/base/video_util.h"
50 #include "skia/ext/image_operations.h"
51 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
52 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
53 #include "third_party/WebKit/public/web/WebInputEvent.h"
54 #include "ui/aura/client/aura_constants.h"
55 #include "ui/aura/client/cursor_client.h"
56 #include "ui/aura/client/cursor_client_observer.h"
57 #include "ui/aura/client/focus_client.h"
58 #include "ui/aura/client/screen_position_client.h"
59 #include "ui/aura/client/window_tree_client.h"
60 #include "ui/aura/env.h"
61 #include "ui/aura/window.h"
62 #include "ui/aura/window_event_dispatcher.h"
63 #include "ui/aura/window_observer.h"
64 #include "ui/aura/window_tracker.h"
65 #include "ui/aura/window_tree_host.h"
66 #include "ui/base/clipboard/scoped_clipboard_writer.h"
67 #include "ui/base/hit_test.h"
68 #include "ui/base/ime/input_method.h"
69 #include "ui/base/ui_base_types.h"
70 #include "ui/compositor/compositor_vsync_manager.h"
71 #include "ui/compositor/layer.h"
72 #include "ui/events/event.h"
73 #include "ui/events/event_utils.h"
74 #include "ui/events/gestures/gesture_recognizer.h"
75 #include "ui/gfx/canvas.h"
76 #include "ui/gfx/display.h"
77 #include "ui/gfx/rect_conversions.h"
78 #include "ui/gfx/screen.h"
79 #include "ui/gfx/size_conversions.h"
80 #include "ui/gfx/skia_util.h"
81 #include "ui/wm/public/activation_client.h"
82 #include "ui/wm/public/scoped_tooltip_disabler.h"
83 #include "ui/wm/public/tooltip_client.h"
84 #include "ui/wm/public/transient_window_client.h"
85 #include "ui/wm/public/window_types.h"
88 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
89 #include "content/browser/accessibility/browser_accessibility_win.h"
90 #include "content/browser/renderer_host/legacy_render_widget_host_win.h"
91 #include "content/common/plugin_constants_win.h"
92 #include "ui/base/win/hidden_window.h"
93 #include "ui/gfx/gdi_util.h"
94 #include "ui/gfx/win/dpi.h"
97 using gfx::RectToSkIRect;
98 using gfx::SkIRectToRect;
100 using blink::WebScreenInfo;
101 using blink::WebTouchEvent;
107 void MailboxReleaseCallback(scoped_ptr<base::SharedMemory> shared_memory,
109 bool lost_resource) {
110 // NOTE: shared_memory will get released when we go out of scope.
113 // In mouse lock mode, we need to prevent the (invisible) cursor from hitting
114 // the border of the view, in order to get valid movement information. However,
115 // forcing the cursor back to the center of the view after each mouse move
116 // doesn't work well. It reduces the frequency of useful mouse move messages
117 // significantly. Therefore, we move the cursor to the center of the view only
118 // if it approaches the border. |kMouseLockBorderPercentage| specifies the width
119 // of the border area, in percentage of the corresponding dimension.
120 const int kMouseLockBorderPercentage = 15;
122 // When accelerated compositing is enabled and a widget resize is pending,
123 // we delay further resizes of the UI. The following constant is the maximum
124 // length of time that we should delay further UI resizes while waiting for a
125 // resized frame from a renderer.
126 const int kResizeLockTimeoutMs = 67;
129 // Used to associate a plugin HWND with its RenderWidgetHostViewAura instance.
130 const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner";
132 BOOL CALLBACK WindowDestroyingCallback(HWND window, LPARAM param) {
133 RenderWidgetHostViewAura* widget =
134 reinterpret_cast<RenderWidgetHostViewAura*>(param);
135 if (GetProp(window, kWidgetOwnerProperty) == widget) {
136 // Properties set on HWNDs must be removed to avoid leaks.
137 RemoveProp(window, kWidgetOwnerProperty);
138 RenderWidgetHostViewBase::DetachPluginWindowsCallback(window);
143 BOOL CALLBACK HideWindowsCallback(HWND window, LPARAM param) {
144 RenderWidgetHostViewAura* widget =
145 reinterpret_cast<RenderWidgetHostViewAura*>(param);
146 if (GetProp(window, kWidgetOwnerProperty) == widget)
147 SetParent(window, ui::GetHiddenWindow());
151 BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) {
152 RenderWidgetHostViewAura* widget =
153 reinterpret_cast<RenderWidgetHostViewAura*>(param);
155 if (GetProp(window, kWidgetOwnerProperty) == widget &&
156 widget->GetNativeView()->GetHost()) {
157 HWND parent = widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
158 SetParent(window, parent);
163 struct CutoutRectsParams {
164 RenderWidgetHostViewAura* widget;
165 std::vector<gfx::Rect> cutout_rects;
166 std::map<HWND, WebPluginGeometry>* geometry;
169 // Used to update the region for the windowed plugin to draw in. We start with
170 // the clip rect from the renderer, then remove the cutout rects from the
171 // renderer, and then remove the transient windows from the root window and the
172 // constrained windows from the parent window.
173 BOOL CALLBACK SetCutoutRectsCallback(HWND window, LPARAM param) {
174 CutoutRectsParams* params = reinterpret_cast<CutoutRectsParams*>(param);
176 if (GetProp(window, kWidgetOwnerProperty) == params->widget) {
177 // First calculate the offset of this plugin from the root window, since
178 // the cutouts are relative to the root window.
180 params->widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
182 offset.x = offset.y = 0;
183 MapWindowPoints(window, parent, &offset, 1);
185 // Now get the cached clip rect and cutouts for this plugin window that came
186 // from the renderer.
187 std::map<HWND, WebPluginGeometry>::iterator i = params->geometry->begin();
188 while (i != params->geometry->end() &&
189 i->second.window != window &&
190 GetParent(i->second.window) != window) {
194 if (i == params->geometry->end()) {
199 HRGN hrgn = CreateRectRgn(i->second.clip_rect.x(),
200 i->second.clip_rect.y(),
201 i->second.clip_rect.right(),
202 i->second.clip_rect.bottom());
203 // We start with the cutout rects that came from the renderer, then add the
204 // ones that came from transient and constrained windows.
205 std::vector<gfx::Rect> cutout_rects = i->second.cutout_rects;
206 for (size_t i = 0; i < params->cutout_rects.size(); ++i) {
207 gfx::Rect offset_cutout = params->cutout_rects[i];
208 offset_cutout.Offset(-offset.x, -offset.y);
209 cutout_rects.push_back(offset_cutout);
211 gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects);
212 // If we don't have any cutout rects then no point in messing with the
214 if (cutout_rects.size())
215 SetWindowRgn(window, hrgn, TRUE);
220 // A callback function for EnumThreadWindows to enumerate and dismiss
221 // any owned popup windows.
222 BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
223 const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);
225 if (::IsWindowVisible(window)) {
226 const HWND owner = ::GetWindow(window, GW_OWNER);
227 if (toplevel_hwnd == owner) {
228 ::PostMessage(window, WM_CANCELMODE, 0, 0);
236 void UpdateWebTouchEventAfterDispatch(blink::WebTouchEvent* event,
237 blink::WebTouchPoint* point) {
238 if (point->state != blink::WebTouchPoint::StateReleased &&
239 point->state != blink::WebTouchPoint::StateCancelled)
241 --event->touchesLength;
242 for (unsigned i = point - event->touches;
243 i < event->touchesLength;
245 event->touches[i] = event->touches[i + 1];
249 bool CanRendererHandleEvent(const ui::MouseEvent* event) {
250 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
254 // Renderer cannot handle WM_XBUTTON or NC events.
255 switch (event->native_event().message) {
258 case WM_XBUTTONDBLCLK:
259 case WM_NCMOUSELEAVE:
261 case WM_NCLBUTTONDOWN:
263 case WM_NCLBUTTONDBLCLK:
264 case WM_NCRBUTTONDOWN:
266 case WM_NCRBUTTONDBLCLK:
267 case WM_NCMBUTTONDOWN:
269 case WM_NCMBUTTONDBLCLK:
270 case WM_NCXBUTTONDOWN:
272 case WM_NCXBUTTONDBLCLK:
277 #elif defined(USE_X11)
278 // Renderer only supports standard mouse buttons, so ignore programmable
280 switch (event->type()) {
281 case ui::ET_MOUSE_PRESSED:
282 case ui::ET_MOUSE_RELEASED:
283 return event->IsAnyButton();
291 // We don't mark these as handled so that they're sent back to the
292 // DefWindowProc so it can generate WM_APPCOMMAND as necessary.
293 bool IsXButtonUpEvent(const ui::MouseEvent* event) {
295 switch (event->native_event().message) {
304 void GetScreenInfoForWindow(WebScreenInfo* results, aura::Window* window) {
305 const gfx::Display display = window ?
306 gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window) :
307 gfx::Screen::GetScreenFor(window)->GetPrimaryDisplay();
308 results->rect = display.bounds();
309 results->availableRect = display.work_area();
310 // TODO(derat|oshima): Don't hardcode this. Get this from display object.
312 results->depthPerComponent = 8;
313 results->deviceScaleFactor = display.device_scale_factor();
316 bool PointerEventActivates(const ui::Event& event) {
317 if (event.type() == ui::ET_MOUSE_PRESSED)
320 if (event.type() == ui::ET_GESTURE_BEGIN) {
321 const ui::GestureEvent& gesture =
322 static_cast<const ui::GestureEvent&>(event);
323 return gesture.details().touch_points() == 1;
329 // Swap ack for the renderer when kCompositeToMailbox is enabled.
330 void SendCompositorFrameAck(
332 uint32 output_surface_id,
333 int renderer_host_id,
334 const gpu::Mailbox& received_mailbox,
335 const gfx::Size& received_size,
337 const scoped_refptr<ui::Texture>& texture_to_produce) {
338 cc::CompositorFrameAck ack;
339 ack.gl_frame_data.reset(new cc::GLFrameData());
340 DCHECK(!texture_to_produce.get() || !skip_frame);
341 if (texture_to_produce.get()) {
342 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
343 ack.gl_frame_data->mailbox = texture_to_produce->Produce();
344 ack.gl_frame_data->size = texture_to_produce->size();
345 ack.gl_frame_data->sync_point =
346 gl_helper ? gl_helper->InsertSyncPoint() : 0;
347 } else if (skip_frame) {
348 // Skip the frame, i.e. tell the producer to reuse the same buffer that
350 ack.gl_frame_data->size = received_size;
351 ack.gl_frame_data->mailbox = received_mailbox;
354 RenderWidgetHostImpl::SendSwapCompositorFrameAck(
355 route_id, output_surface_id, renderer_host_id, ack);
358 void AcknowledgeBufferForGpu(
361 const gpu::Mailbox& received_mailbox,
363 const scoped_refptr<ui::Texture>& texture_to_produce) {
364 AcceleratedSurfaceMsg_BufferPresented_Params ack;
365 uint32 sync_point = 0;
366 DCHECK(!texture_to_produce.get() || !skip_frame);
367 if (texture_to_produce.get()) {
368 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
369 ack.mailbox = texture_to_produce->Produce();
370 sync_point = gl_helper ? gl_helper->InsertSyncPoint() : 0;
371 } else if (skip_frame) {
372 ack.mailbox = received_mailbox;
376 ack.sync_point = sync_point;
377 RenderWidgetHostImpl::AcknowledgeBufferPresent(
378 route_id, gpu_host_id, ack);
383 // We need to watch for mouse events outside a Web Popup or its parent
384 // and dismiss the popup for certain events.
385 class RenderWidgetHostViewAura::EventFilterForPopupExit
386 : public ui::EventHandler {
388 explicit EventFilterForPopupExit(RenderWidgetHostViewAura* rwhva)
391 aura::Env::GetInstance()->AddPreTargetHandler(this);
394 virtual ~EventFilterForPopupExit() {
395 aura::Env::GetInstance()->RemovePreTargetHandler(this);
398 // Overridden from ui::EventHandler
399 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
400 rwhva_->ApplyEventFilterForPopupExit(event);
403 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
404 rwhva_->ApplyEventFilterForPopupExit(event);
408 RenderWidgetHostViewAura* rwhva_;
410 DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit);
413 void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
414 ui::LocatedEvent* event) {
415 if (in_shutdown_ || is_fullscreen_ || !event->target())
418 if (event->type() != ui::ET_MOUSE_PRESSED &&
419 event->type() != ui::ET_TOUCH_PRESSED) {
423 aura::Window* target = static_cast<aura::Window*>(event->target());
424 if (target != window_ &&
425 (!popup_parent_host_view_ ||
426 target != popup_parent_host_view_->window_)) {
427 // Note: popup_parent_host_view_ may be NULL when there are multiple
428 // popup children per view. See: RenderWidgetHostViewAura::InitAsPopup().
434 // We have to implement the WindowObserver interface on a separate object
435 // because clang doesn't like implementing multiple interfaces that have
436 // methods with the same name. This object is owned by the
437 // RenderWidgetHostViewAura.
438 class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver {
440 explicit WindowObserver(RenderWidgetHostViewAura* view)
442 view_->window_->AddObserver(this);
445 virtual ~WindowObserver() {
446 view_->window_->RemoveObserver(this);
449 // Overridden from aura::WindowObserver:
450 virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
451 if (window == view_->window_)
452 view_->AddedToRootWindow();
455 virtual void OnWindowRemovingFromRootWindow(aura::Window* window,
456 aura::Window* new_root) OVERRIDE {
457 if (window == view_->window_)
458 view_->RemovingFromRootWindow();
462 RenderWidgetHostViewAura* view_;
464 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
467 ////////////////////////////////////////////////////////////////////////////////
468 // RenderWidgetHostViewAura, public:
470 RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
471 : host_(RenderWidgetHostImpl::From(host)),
472 window_(new aura::Window(this)),
474 in_bounds_changed_(false),
475 is_fullscreen_(false),
476 popup_parent_host_view_(NULL),
477 popup_child_host_view_(NULL),
479 text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
480 text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
481 can_compose_inline_(true),
482 has_composition_text_(false),
483 accept_return_character_(false),
484 last_output_surface_id_(0),
485 pending_delegated_ack_count_(0),
486 skipped_frames_(false),
487 last_swapped_surface_scale_factor_(1.f),
489 synthetic_move_sent_(false),
490 accelerated_compositing_state_changed_(false),
491 can_lock_compositor_(YES),
492 cursor_visibility_state_in_renderer_(UNKNOWN),
493 touch_editing_client_(NULL),
494 delegated_frame_evictor_(new DelegatedFrameEvictor(this)),
495 weak_ptr_factory_(this) {
496 host_->SetView(this);
497 window_observer_.reset(new WindowObserver(this));
498 aura::client::SetTooltipText(window_, &tooltip_);
499 aura::client::SetActivationDelegate(window_, this);
500 aura::client::SetActivationChangeObserver(window_, this);
501 aura::client::SetFocusChangeObserver(window_, this);
502 window_->set_layer_owner_delegate(this);
503 gfx::Screen::GetScreenFor(window_)->AddObserver(this);
504 software_frame_manager_.reset(new SoftwareFrameManager(
505 weak_ptr_factory_.GetWeakPtr()));
506 ImageTransportFactory::GetInstance()->AddObserver(this);
509 ////////////////////////////////////////////////////////////////////////////////
510 // RenderWidgetHostViewAura, RenderWidgetHostView implementation:
512 bool RenderWidgetHostViewAura::OnMessageReceived(
513 const IPC::Message& message) {
515 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAura, message)
516 // TODO(kevers): Move to RenderWidgetHostViewImpl and consolidate IPC
517 // messages for TextInput<State|Type>Changed. Corresponding code in
518 // RenderWidgetHostViewAndroid should also be moved at the same time.
519 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
520 OnTextInputStateChanged)
521 IPC_MESSAGE_UNHANDLED(handled = false)
522 IPC_END_MESSAGE_MAP()
526 void RenderWidgetHostViewAura::InitAsChild(
527 gfx::NativeView parent_view) {
528 window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
529 window_->Init(aura::WINDOW_LAYER_TEXTURED);
530 window_->SetName("RenderWidgetHostViewAura");
533 void RenderWidgetHostViewAura::InitAsPopup(
534 RenderWidgetHostView* parent_host_view,
535 const gfx::Rect& bounds_in_screen) {
536 popup_parent_host_view_ =
537 static_cast<RenderWidgetHostViewAura*>(parent_host_view);
539 // TransientWindowClient may be NULL during tests.
540 aura::client::TransientWindowClient* transient_window_client =
541 aura::client::GetTransientWindowClient();
542 RenderWidgetHostViewAura* old_child =
543 popup_parent_host_view_->popup_child_host_view_;
545 // TODO(jhorwich): Allow multiple popup_child_host_view_ per view, or
546 // similar mechanism to ensure a second popup doesn't cause the first one
547 // to never get a chance to filter events. See crbug.com/160589.
548 DCHECK(old_child->popup_parent_host_view_ == popup_parent_host_view_);
549 if (transient_window_client) {
550 transient_window_client->RemoveTransientChild(
551 popup_parent_host_view_->window_, old_child->window_);
553 old_child->popup_parent_host_view_ = NULL;
555 popup_parent_host_view_->popup_child_host_view_ = this;
556 window_->SetType(ui::wm::WINDOW_TYPE_MENU);
557 window_->Init(aura::WINDOW_LAYER_TEXTURED);
558 window_->SetName("RenderWidgetHostViewAura");
560 aura::Window* root = popup_parent_host_view_->window_->GetRootWindow();
561 aura::client::ParentWindowWithContext(window_, root, bounds_in_screen);
562 // Setting the transient child allows for the popup to get mouse events when
563 // in a system modal dialog.
564 // This fixes crbug.com/328593.
565 if (transient_window_client) {
566 transient_window_client->AddTransientChild(
567 popup_parent_host_view_->window_, window_);
570 SetBounds(bounds_in_screen);
572 #if !defined(OS_WIN) && !defined(OS_CHROMEOS)
573 if (NeedsInputGrab())
574 window_->SetCapture();
577 event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
580 void RenderWidgetHostViewAura::InitAsFullscreen(
581 RenderWidgetHostView* reference_host_view) {
582 is_fullscreen_ = true;
583 window_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
584 window_->Init(aura::WINDOW_LAYER_TEXTURED);
585 window_->SetName("RenderWidgetHostViewAura");
586 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
588 aura::Window* parent = NULL;
590 if (reference_host_view) {
591 aura::Window* reference_window =
592 static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_;
593 if (reference_window) {
594 host_tracker_.reset(new aura::WindowTracker);
595 host_tracker_->Add(reference_window);
597 gfx::Display display = gfx::Screen::GetScreenFor(window_)->
598 GetDisplayNearestWindow(reference_window);
599 parent = reference_window->GetRootWindow();
600 bounds = display.bounds();
602 aura::client::ParentWindowWithContext(window_, parent, bounds);
607 RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
611 void RenderWidgetHostViewAura::WasShown() {
613 if (!host_->is_hidden())
616 software_frame_manager_->SetVisibility(true);
617 delegated_frame_evictor_->SetVisible(true);
619 aura::Window* root = window_->GetRootWindow();
621 aura::client::CursorClient* cursor_client =
622 aura::client::GetCursorClient(root);
624 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
627 if (!current_surface_.get() && host_->is_accelerated_compositing_active() &&
628 !released_front_lock_.get()) {
629 ui::Compositor* compositor = GetCompositor();
631 released_front_lock_ = compositor->GetCompositorLock();
635 if (legacy_render_widget_host_HWND_) {
636 // Reparent the legacy Chrome_RenderWidgetHostHWND window to the parent
637 // window before reparenting any plugins. This ensures that the plugin
638 // windows stay on top of the child Zorder in the parent and receive
639 // mouse events, etc.
640 legacy_render_widget_host_HWND_->UpdateParent(
641 GetNativeView()->GetHost()->GetAcceleratedWidget());
642 legacy_render_widget_host_HWND_->SetBounds(
643 window_->GetBoundsInRootWindow());
645 LPARAM lparam = reinterpret_cast<LPARAM>(this);
646 EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
650 void RenderWidgetHostViewAura::WasHidden() {
651 if (!host_ || host_->is_hidden())
654 software_frame_manager_->SetVisibility(false);
655 delegated_frame_evictor_->SetVisible(false);
656 released_front_lock_ = NULL;
659 constrained_rects_.clear();
660 aura::WindowTreeHost* host = window_->GetHost();
662 HWND parent = host->GetAcceleratedWidget();
663 LPARAM lparam = reinterpret_cast<LPARAM>(this);
664 EnumChildWindows(parent, HideWindowsCallback, lparam);
665 // We reparent the legacy Chrome_RenderWidgetHostHWND window to the global
666 // hidden window on the same lines as Windowed plugin windows.
667 if (legacy_render_widget_host_HWND_)
668 legacy_render_widget_host_HWND_->UpdateParent(ui::GetHiddenWindow());
673 void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) {
674 // For a SetSize operation, we don't care what coordinate system the origin
675 // of the window is in, it's only important to make sure that the origin
676 // remains constant after the operation.
677 InternalSetBounds(gfx::Rect(window_->bounds().origin(), size));
680 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
681 gfx::Point relative_origin(rect.origin());
683 // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but
684 // Window::SetBounds() takes parent coordinates, so do the conversion here.
685 aura::Window* root = window_->GetRootWindow();
687 aura::client::ScreenPositionClient* screen_position_client =
688 aura::client::GetScreenPositionClient(root);
689 if (screen_position_client) {
690 screen_position_client->ConvertPointFromScreen(
691 window_->parent(), &relative_origin);
695 InternalSetBounds(gfx::Rect(relative_origin, rect.size()));
698 void RenderWidgetHostViewAura::MaybeCreateResizeLock() {
699 if (!ShouldCreateResizeLock())
701 DCHECK(window_->GetHost());
702 DCHECK(window_->GetHost()->compositor());
704 // Listen to changes in the compositor lock state.
705 ui::Compositor* compositor = window_->GetHost()->compositor();
706 if (!compositor->HasObserver(this))
707 compositor->AddObserver(this);
709 bool defer_compositor_lock =
710 can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
711 can_lock_compositor_ == NO_PENDING_COMMIT;
713 if (can_lock_compositor_ == YES)
714 can_lock_compositor_ = YES_DID_LOCK;
716 resize_lock_ = CreateResizeLock(defer_compositor_lock);
719 bool RenderWidgetHostViewAura::ShouldCreateResizeLock() {
720 // On Windows while resizing, the the resize locks makes us mis-paint a white
721 // vertical strip (including the non-client area) if the content composition
722 // is lagging the UI composition. So here we disable the throttling so that
723 // the UI bits can draw ahead of the content thereby reducing the amount of
724 // whiteout. Because this causes the content to be drawn at wrong sizes while
725 // resizing we compensate by blocking the UI thread in Compositor::Draw() by
726 // issuing a FinishAllRendering() if we are resizing.
733 if (host_->should_auto_resize())
735 if (!host_->is_accelerated_compositing_active())
738 gfx::Size desired_size = window_->bounds().size();
739 if (desired_size == current_frame_size_)
742 aura::WindowTreeHost* host = window_->GetHost();
746 ui::Compositor* compositor = host->compositor();
754 scoped_ptr<ResizeLock> RenderWidgetHostViewAura::CreateResizeLock(
755 bool defer_compositor_lock) {
756 gfx::Size desired_size = window_->bounds().size();
757 return scoped_ptr<ResizeLock>(new CompositorResizeLock(
760 defer_compositor_lock,
761 base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs)));
764 void RenderWidgetHostViewAura::RequestCopyOfOutput(
765 scoped_ptr<cc::CopyOutputRequest> request) {
766 window_->layer()->RequestCopyOfOutput(request.Pass());
769 gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
773 gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const {
775 aura::WindowTreeHost* host = window_->GetHost();
777 return reinterpret_cast<gfx::NativeViewId>(host->GetAcceleratedWidget());
779 return static_cast<gfx::NativeViewId>(NULL);
782 gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
784 aura::WindowTreeHost* host = window_->GetHost();
786 return static_cast<gfx::NativeViewAccessible>(NULL);
787 HWND hwnd = host->GetAcceleratedWidget();
789 CreateBrowserAccessibilityManagerIfNeeded();
790 BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
792 return manager->GetRoot()->ToBrowserAccessibilityWin();
796 return static_cast<gfx::NativeViewAccessible>(NULL);
799 void RenderWidgetHostViewAura::SetKeyboardFocus() {
802 aura::WindowTreeHost* host = window_->GetHost();
804 ::SetFocus(host->GetAcceleratedWidget());
809 RenderFrameHostImpl* RenderWidgetHostViewAura::GetFocusedFrame() {
810 if (!host_->IsRenderView())
812 RenderViewHost* rvh = RenderViewHost::From(host_);
813 FrameTreeNode* focused_frame =
814 rvh->GetDelegate()->GetFrameTree()->GetFocusedFrame();
818 return focused_frame->current_frame_host();
821 void RenderWidgetHostViewAura::MovePluginWindows(
822 const gfx::Vector2d& scroll_offset,
823 const std::vector<WebPluginGeometry>& plugin_window_moves) {
825 // We need to clip the rectangle to the tab's viewport, otherwise we will draw
826 // over the browser UI.
827 if (!window_->GetRootWindow()) {
828 DCHECK(plugin_window_moves.empty());
831 HWND parent = window_->GetHost()->GetAcceleratedWidget();
832 gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
833 std::vector<WebPluginGeometry> moves = plugin_window_moves;
835 gfx::Rect view_port(scroll_offset.x(), scroll_offset.y(), view_bounds.width(),
836 view_bounds.height());
838 for (size_t i = 0; i < moves.size(); ++i) {
839 gfx::Rect clip(moves[i].clip_rect);
840 gfx::Vector2d view_port_offset(
841 moves[i].window_rect.OffsetFromOrigin() + scroll_offset);
842 clip.Offset(view_port_offset);
843 clip.Intersect(view_port);
844 clip.Offset(-view_port_offset);
845 moves[i].clip_rect = clip;
847 moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin());
849 plugin_window_moves_[moves[i].window] = moves[i];
851 // constrained_rects_ are relative to the root window. We want to convert
852 // them to be relative to the plugin window.
853 for (size_t j = 0; j < constrained_rects_.size(); ++j) {
854 gfx::Rect offset_cutout = constrained_rects_[j];
855 offset_cutout -= moves[i].window_rect.OffsetFromOrigin();
856 moves[i].cutout_rects.push_back(offset_cutout);
860 MovePluginWindowsHelper(parent, moves);
862 // Make sure each plugin window (or its wrapper if it exists) has a pointer to
864 for (size_t i = 0; i < moves.size(); ++i) {
865 HWND window = moves[i].window;
866 if (GetParent(window) != parent) {
867 window = GetParent(window);
869 if (!GetProp(window, kWidgetOwnerProperty))
870 SetProp(window, kWidgetOwnerProperty, this);
872 #endif // defined(OS_WIN)
875 void RenderWidgetHostViewAura::Focus() {
876 // Make sure we have a FocusClient before attempting to Focus(). In some
877 // situations we may not yet be in a valid Window hierarchy (such as reloading
878 // after out of memory discarded the tab).
879 aura::client::FocusClient* client = aura::client::GetFocusClient(window_);
884 void RenderWidgetHostViewAura::Blur() {
888 bool RenderWidgetHostViewAura::HasFocus() const {
889 return window_->HasFocus();
892 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
893 return CanCopyToBitmap() || !!host_->GetBackingStore(false);
896 void RenderWidgetHostViewAura::Show() {
900 if (legacy_render_widget_host_HWND_)
901 legacy_render_widget_host_HWND_->Show();
905 void RenderWidgetHostViewAura::Hide() {
909 if (legacy_render_widget_host_HWND_)
910 legacy_render_widget_host_HWND_->Hide();
914 bool RenderWidgetHostViewAura::IsShowing() {
915 return window_->IsVisible();
918 gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
919 // This is the size that we want the renderer to produce. While we're waiting
920 // for the correct frame (i.e. during a resize), don't change the size so that
921 // we don't pipeline more resizes than we can handle.
922 gfx::Rect bounds(window_->GetBoundsInScreen());
923 if (resize_lock_.get())
924 return gfx::Rect(bounds.origin(), resize_lock_->expected_size());
929 void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) {
930 RenderWidgetHostViewBase::SetBackground(background);
931 host_->SetBackground(background);
932 window_->layer()->SetFillsBoundsOpaquely(background.isOpaque());
935 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
936 current_cursor_ = cursor;
937 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
938 GetDisplayNearestWindow(window_);
939 current_cursor_.SetDisplayInfo(display);
940 UpdateCursorIfOverSelf();
943 void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
944 is_loading_ = is_loading;
945 UpdateCursorIfOverSelf();
948 void RenderWidgetHostViewAura::TextInputTypeChanged(
949 ui::TextInputType type,
950 ui::TextInputMode input_mode,
951 bool can_compose_inline) {
952 if (text_input_type_ != type ||
953 text_input_mode_ != input_mode ||
954 can_compose_inline_ != can_compose_inline) {
955 text_input_type_ = type;
956 text_input_mode_ = input_mode;
957 can_compose_inline_ = can_compose_inline;
958 if (GetInputMethod())
959 GetInputMethod()->OnTextInputTypeChanged(this);
960 if (touch_editing_client_)
961 touch_editing_client_->OnTextInputTypeChanged(text_input_type_);
965 void RenderWidgetHostViewAura::OnTextInputStateChanged(
966 const ViewHostMsg_TextInputState_Params& params) {
967 if (params.show_ime_if_needed && params.type != ui::TEXT_INPUT_TYPE_NONE) {
968 if (GetInputMethod())
969 GetInputMethod()->ShowImeIfNeeded();
973 void RenderWidgetHostViewAura::ImeCancelComposition() {
974 if (GetInputMethod())
975 GetInputMethod()->CancelComposition(this);
976 has_composition_text_ = false;
979 void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
980 const gfx::Range& range,
981 const std::vector<gfx::Rect>& character_bounds) {
982 composition_character_bounds_ = character_bounds;
985 void RenderWidgetHostViewAura::DidUpdateBackingStore(
986 const gfx::Rect& scroll_rect,
987 const gfx::Vector2d& scroll_delta,
988 const std::vector<gfx::Rect>& copy_rects,
989 const std::vector<ui::LatencyInfo>& latency_info) {
990 if (accelerated_compositing_state_changed_)
991 UpdateExternalTexture();
993 for (size_t i = 0; i < latency_info.size(); i++)
994 software_latency_info_.push_back(latency_info[i]);
996 // Use the state of the RenderWidgetHost and not the window as the two may
997 // differ. In particular if the window is hidden but the renderer isn't and we
998 // ignore the update and the window is made visible again the layer isn't
999 // marked as dirty and we show the wrong thing.
1000 // We do this after UpdateExternalTexture() so that when we become visible
1001 // we're not drawing a stale texture.
1002 if (host_->is_hidden())
1005 gfx::Rect clip_rect;
1006 if (paint_canvas_) {
1007 SkRect sk_clip_rect;
1008 if (paint_canvas_->sk_canvas()->getClipBounds(&sk_clip_rect))
1009 clip_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(sk_clip_rect));
1012 if (!scroll_rect.IsEmpty())
1013 SchedulePaintIfNotInClip(scroll_rect, clip_rect);
1016 aura::WindowTreeHost* host = window_->GetHost();
1018 for (size_t i = 0; i < copy_rects.size(); ++i) {
1019 gfx::Rect rect = gfx::SubtractRects(copy_rects[i], scroll_rect);
1023 SchedulePaintIfNotInClip(rect, clip_rect);
1027 // Send the invalid rect in screen coordinates.
1028 gfx::Rect screen_rect = GetViewBounds();
1029 gfx::Rect invalid_screen_rect(rect);
1030 invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y());
1031 HWND hwnd = host->GetAcceleratedWidget();
1032 PaintPluginWindowsHelper(hwnd, invalid_screen_rect);
1034 #endif // defined(OS_WIN)
1038 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
1040 UpdateCursorIfOverSelf();
1044 void RenderWidgetHostViewAura::Destroy() {
1045 // Beware, this function is not called on all destruction paths. It will
1046 // implicitly end up calling ~RenderWidgetHostViewAura though, so all
1047 // destruction/cleanup code should happen there, not here.
1048 in_shutdown_ = true;
1052 void RenderWidgetHostViewAura::SetTooltipText(
1053 const base::string16& tooltip_text) {
1054 tooltip_ = tooltip_text;
1055 aura::Window* root_window = window_->GetRootWindow();
1056 aura::client::TooltipClient* tooltip_client =
1057 aura::client::GetTooltipClient(root_window);
1058 if (tooltip_client) {
1059 tooltip_client->UpdateTooltip(window_);
1060 // Content tooltips should be visible indefinitely.
1061 tooltip_client->SetTooltipShownTimeout(window_, 0);
1065 void RenderWidgetHostViewAura::SelectionChanged(const base::string16& text,
1067 const gfx::Range& range) {
1068 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
1070 #if defined(USE_X11) && !defined(OS_CHROMEOS)
1071 if (text.empty() || range.is_empty())
1073 size_t pos = range.GetMin() - offset;
1074 size_t n = range.length();
1076 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
1077 if (pos >= text.length()) {
1078 NOTREACHED() << "The text can not cover range.";
1082 // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard.
1083 ui::ScopedClipboardWriter clipboard_writer(
1084 ui::Clipboard::GetForCurrentThread(),
1085 ui::CLIPBOARD_TYPE_SELECTION);
1086 clipboard_writer.WriteText(text.substr(pos, n));
1087 #endif // defined(USE_X11) && !defined(OS_CHROMEOS)
1090 void RenderWidgetHostViewAura::SelectionBoundsChanged(
1091 const ViewHostMsg_SelectionBounds_Params& params) {
1092 if (selection_anchor_rect_ == params.anchor_rect &&
1093 selection_focus_rect_ == params.focus_rect)
1096 selection_anchor_rect_ = params.anchor_rect;
1097 selection_focus_rect_ = params.focus_rect;
1099 if (GetInputMethod())
1100 GetInputMethod()->OnCaretBoundsChanged(this);
1102 if (touch_editing_client_) {
1103 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
1104 selection_focus_rect_);
1108 void RenderWidgetHostViewAura::ScrollOffsetChanged() {
1109 aura::Window* root = window_->GetRootWindow();
1112 aura::client::CursorClient* cursor_client =
1113 aura::client::GetCursorClient(root);
1114 if (cursor_client && !cursor_client->IsCursorVisible())
1115 cursor_client->DisableMouseEvents();
1118 BackingStore* RenderWidgetHostViewAura::AllocBackingStore(
1119 const gfx::Size& size) {
1120 return new BackingStoreAura(host_, size);
1123 void RenderWidgetHostViewAura::CopyFromCompositingSurface(
1124 const gfx::Rect& src_subrect,
1125 const gfx::Size& dst_size,
1126 const base::Callback<void(bool, const SkBitmap&)>& callback,
1127 const SkBitmap::Config config) {
1128 // Only ARGB888 and RGB565 supported as of now.
1129 bool format_support = ((config == SkBitmap::kRGB_565_Config) ||
1130 (config == SkBitmap::kARGB_8888_Config));
1131 if (!format_support) {
1132 DCHECK(format_support);
1133 callback.Run(false, SkBitmap());
1136 if (!CanCopyToBitmap()) {
1137 callback.Run(false, SkBitmap());
1141 const gfx::Size& dst_size_in_pixel = ConvertViewSizeToPixel(this, dst_size);
1142 scoped_ptr<cc::CopyOutputRequest> request =
1143 cc::CopyOutputRequest::CreateRequest(base::Bind(
1144 &RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult,
1148 gfx::Rect src_subrect_in_pixel =
1149 ConvertRectToPixel(current_device_scale_factor_, src_subrect);
1150 request->set_area(src_subrect_in_pixel);
1151 RequestCopyOfOutput(request.Pass());
1154 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
1155 const gfx::Rect& src_subrect,
1156 const scoped_refptr<media::VideoFrame>& target,
1157 const base::Callback<void(bool)>& callback) {
1158 if (!CanCopyToVideoFrame()) {
1159 callback.Run(false);
1163 // Try get a texture to reuse.
1164 scoped_refptr<OwnedMailbox> subscriber_texture;
1165 if (frame_subscriber_) {
1166 if (!idle_frame_subscriber_textures_.empty()) {
1167 subscriber_texture = idle_frame_subscriber_textures_.back();
1168 idle_frame_subscriber_textures_.pop_back();
1169 } else if (GLHelper* helper =
1170 ImageTransportFactory::GetInstance()->GetGLHelper()) {
1171 subscriber_texture = new OwnedMailbox(helper);
1173 if (subscriber_texture.get())
1174 active_frame_subscriber_textures_.insert(subscriber_texture.get());
1177 scoped_ptr<cc::CopyOutputRequest> request =
1178 cc::CopyOutputRequest::CreateRequest(base::Bind(
1179 &RenderWidgetHostViewAura::
1180 CopyFromCompositingSurfaceHasResultForVideo,
1181 AsWeakPtr(), // For caching the ReadbackYUVInterface on this class.
1185 gfx::Rect src_subrect_in_pixel =
1186 ConvertRectToPixel(current_device_scale_factor_, src_subrect);
1187 request->set_area(src_subrect_in_pixel);
1188 if (subscriber_texture.get()) {
1189 request->SetTextureMailbox(
1190 cc::TextureMailbox(subscriber_texture->mailbox(),
1191 subscriber_texture->target(),
1192 subscriber_texture->sync_point()));
1194 RequestCopyOfOutput(request.Pass());
1197 bool RenderWidgetHostViewAura::CanCopyToBitmap() const {
1198 return GetCompositor() && window_->layer()->has_external_content();
1201 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
1202 return GetCompositor() &&
1203 window_->layer()->has_external_content() &&
1204 host_->is_accelerated_compositing_active();
1207 bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
1211 void RenderWidgetHostViewAura::BeginFrameSubscription(
1212 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1213 frame_subscriber_ = subscriber.Pass();
1216 void RenderWidgetHostViewAura::EndFrameSubscription() {
1217 idle_frame_subscriber_textures_.clear();
1218 frame_subscriber_.reset();
1221 void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() {
1222 // Delay processing the state change until we either get a software frame if
1223 // switching to software mode or receive a buffers swapped notification
1224 // if switching to accelerated mode.
1225 // Sometimes (e.g. on a page load) the renderer will spuriously disable then
1226 // re-enable accelerated compositing, causing us to flash.
1227 // TODO(piman): factor the enable/disable accelerated compositing message into
1228 // the UpdateRect/AcceleratedSurfaceBuffersSwapped messages so that we have
1229 // fewer inconsistent temporary states.
1230 accelerated_compositing_state_changed_ = true;
1233 void RenderWidgetHostViewAura::AcceleratedSurfaceInitialized(int host_id,
1237 bool RenderWidgetHostViewAura::ShouldSkipFrame(gfx::Size size_in_dip) const {
1238 if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
1239 can_lock_compositor_ == NO_PENDING_COMMIT ||
1240 !resize_lock_.get())
1243 return size_in_dip != resize_lock_->expected_size();
1246 void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
1247 if (HasDisplayPropertyChanged(window_))
1248 host_->InvalidateScreenInfo();
1250 // Don't recursively call SetBounds if this bounds update is the result of
1251 // a Window::SetBoundsInternal call.
1252 if (!in_bounds_changed_)
1253 window_->SetBounds(rect);
1254 host_->WasResized();
1255 MaybeCreateResizeLock();
1256 if (touch_editing_client_) {
1257 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
1258 selection_focus_rect_);
1261 // Create the legacy dummy window which corresponds to the bounds of the
1262 // webcontents. This will be passed as the container window for windowless
1264 // Plugins like Flash assume the container window which is returned via the
1265 // NPNVnetscapeWindow property corresponds to the bounds of the webpage.
1266 // This is not true in Aura where we have only HWND which is the main Aura
1267 // window. If we return this window to plugins like Flash then it causes the
1268 // coordinate translations done by these plugins to break.
1269 // Additonally the legacy dummy window is needed for accessibility and for
1270 // scrolling to work in legacy drivers for trackpoints/trackpads, etc.
1271 if (GetNativeViewId()) {
1272 if (!legacy_render_widget_host_HWND_) {
1273 legacy_render_widget_host_HWND_ = LegacyRenderWidgetHostHWND::Create(
1274 reinterpret_cast<HWND>(GetNativeViewId()));
1276 if (legacy_render_widget_host_HWND_) {
1277 legacy_render_widget_host_HWND_->SetBounds(
1278 window_->GetBoundsInRootWindow());
1283 UpdateMouseLockRegion();
1287 void RenderWidgetHostViewAura::CheckResizeLock() {
1288 if (!resize_lock_ || resize_lock_->expected_size() != current_frame_size_)
1291 // Since we got the size we were looking for, unlock the compositor. But delay
1292 // the release of the lock until we've kicked a frame with the new texture, to
1293 // avoid resizing the UI before we have a chance to draw a "good" frame.
1294 resize_lock_->UnlockCompositor();
1295 ui::Compositor* compositor = GetCompositor();
1297 if (!compositor->HasObserver(this))
1298 compositor->AddObserver(this);
1302 void RenderWidgetHostViewAura::UpdateExternalTexture() {
1303 // Delay processing accelerated compositing state change till here where we
1304 // act upon the state change. (Clear the external texture if switching to
1305 // software mode or set the external texture if going to accelerated mode).
1306 if (accelerated_compositing_state_changed_)
1307 accelerated_compositing_state_changed_ = false;
1309 bool is_compositing_active = host_->is_accelerated_compositing_active();
1310 if (is_compositing_active && current_surface_.get()) {
1311 window_->layer()->SetExternalTexture(current_surface_.get());
1312 current_frame_size_ = ConvertSizeToDIP(
1313 current_surface_->device_scale_factor(), current_surface_->size());
1315 software_frame_manager_->DiscardCurrentFrame();
1316 } else if (is_compositing_active &&
1317 software_frame_manager_->HasCurrentFrame()) {
1318 cc::TextureMailbox mailbox;
1319 scoped_ptr<cc::SingleReleaseCallback> callback;
1320 software_frame_manager_->GetCurrentFrameMailbox(&mailbox, &callback);
1321 window_->layer()->SetTextureMailbox(mailbox,
1323 last_swapped_surface_scale_factor_);
1324 current_frame_size_ = ConvertSizeToDIP(last_swapped_surface_scale_factor_,
1325 mailbox.shared_memory_size());
1328 window_->layer()->SetShowPaintedContent();
1329 resize_lock_.reset();
1330 host_->WasResized();
1331 software_frame_manager_->DiscardCurrentFrame();
1335 bool RenderWidgetHostViewAura::SwapBuffersPrepare(
1336 const gfx::Rect& surface_rect,
1337 float surface_scale_factor,
1338 const gfx::Rect& damage_rect,
1339 const gpu::Mailbox& mailbox,
1340 const BufferPresentedCallback& ack_callback) {
1341 if (last_swapped_surface_size_ != surface_rect.size()) {
1342 // The surface could have shrunk since we skipped an update, in which
1343 // case we can expect a full update.
1344 DLOG_IF(ERROR, damage_rect != surface_rect) << "Expected full damage rect";
1345 skipped_damage_.setEmpty();
1346 last_swapped_surface_size_ = surface_rect.size();
1347 last_swapped_surface_scale_factor_ = surface_scale_factor;
1350 if (ShouldSkipFrame(ConvertSizeToDIP(surface_scale_factor,
1351 surface_rect.size())) ||
1353 skipped_damage_.op(RectToSkIRect(damage_rect), SkRegion::kUnion_Op);
1354 ack_callback.Run(true, scoped_refptr<ui::Texture>());
1358 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
1360 factory->CreateTransportClient(surface_scale_factor);
1361 if (!current_surface_.get()) {
1362 LOG(ERROR) << "Failed to create ImageTransport texture";
1363 ack_callback.Run(true, scoped_refptr<ui::Texture>());
1367 current_surface_->Consume(mailbox, surface_rect.size());
1368 released_front_lock_ = NULL;
1369 UpdateExternalTexture();
1374 void RenderWidgetHostViewAura::SwapBuffersCompleted(
1375 const BufferPresentedCallback& ack_callback,
1376 const scoped_refptr<ui::Texture>& texture_to_return) {
1377 ui::Compositor* compositor = GetCompositor();
1379 ack_callback.Run(false, texture_to_return);
1381 AddOnCommitCallbackAndDisableLocks(
1382 base::Bind(ack_callback, false, texture_to_return));
1385 DidReceiveFrameFromRenderer();
1388 void RenderWidgetHostViewAura::DidReceiveFrameFromRenderer() {
1389 if (frame_subscriber() && CanCopyToVideoFrame()) {
1390 const base::TimeTicks present_time = base::TimeTicks::Now();
1391 scoped_refptr<media::VideoFrame> frame;
1392 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
1393 if (frame_subscriber()->ShouldCaptureFrame(present_time,
1394 &frame, &callback)) {
1395 CopyFromCompositingSurfaceToVideoFrame(
1396 gfx::Rect(current_frame_size_),
1398 base::Bind(callback, present_time));
1404 void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
1405 const std::vector<gfx::Rect>& rects) {
1406 // Check this before setting constrained_rects_, so that next time they're set
1407 // and we have a root window we don't early return.
1408 if (!window_->GetHost())
1411 if (rects == constrained_rects_)
1414 constrained_rects_ = rects;
1416 HWND parent = window_->GetHost()->GetAcceleratedWidget();
1417 CutoutRectsParams params;
1418 params.widget = this;
1419 params.cutout_rects = constrained_rects_;
1420 params.geometry = &plugin_window_moves_;
1421 LPARAM lparam = reinterpret_cast<LPARAM>(¶ms);
1422 EnumChildWindows(parent, SetCutoutRectsCallback, lparam);
1425 void RenderWidgetHostViewAura::UpdateMouseLockRegion() {
1426 // Clip the cursor if chrome is running on regular desktop.
1427 if (gfx::Screen::GetScreenFor(window_) == gfx::Screen::GetNativeScreen()) {
1428 RECT window_rect = window_->GetBoundsInScreen().ToRECT();
1429 ::ClipCursor(&window_rect);
1434 void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
1435 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
1437 BufferPresentedCallback ack_callback = base::Bind(
1438 &AcknowledgeBufferForGpu,
1439 params_in_pixel.route_id,
1441 params_in_pixel.mailbox);
1442 BuffersSwapped(params_in_pixel.size,
1443 gfx::Rect(params_in_pixel.size),
1444 params_in_pixel.scale_factor,
1445 params_in_pixel.mailbox,
1446 params_in_pixel.latency_info,
1450 void RenderWidgetHostViewAura::SwapDelegatedFrame(
1451 uint32 output_surface_id,
1452 scoped_ptr<cc::DelegatedFrameData> frame_data,
1453 float frame_device_scale_factor,
1454 const std::vector<ui::LatencyInfo>& latency_info) {
1455 DCHECK_NE(0u, frame_data->render_pass_list.size());
1457 cc::RenderPass* root_pass = frame_data->render_pass_list.back();
1459 gfx::Size frame_size = root_pass->output_rect.size();
1460 gfx::Size frame_size_in_dip =
1461 ConvertSizeToDIP(frame_device_scale_factor, frame_size);
1463 gfx::Rect damage_rect = gfx::ToEnclosingRect(root_pass->damage_rect);
1464 damage_rect.Intersect(gfx::Rect(frame_size));
1465 gfx::Rect damage_rect_in_dip =
1466 ConvertRectToDIP(frame_device_scale_factor, damage_rect);
1468 software_frame_manager_->DiscardCurrentFrame();
1470 if (ShouldSkipFrame(frame_size_in_dip)) {
1471 cc::CompositorFrameAck ack;
1472 cc::TransferableResource::ReturnResources(frame_data->resource_list,
1474 RenderWidgetHostImpl::SendSwapCompositorFrameAck(
1475 host_->GetRoutingID(), output_surface_id,
1476 host_->GetProcess()->GetID(), ack);
1477 skipped_frames_ = true;
1481 if (skipped_frames_) {
1482 skipped_frames_ = false;
1483 damage_rect = gfx::Rect(frame_size);
1484 damage_rect_in_dip = gfx::Rect(frame_size_in_dip);
1486 // Give the same damage rect to the compositor.
1487 cc::RenderPass* root_pass = frame_data->render_pass_list.back();
1488 root_pass->damage_rect = damage_rect;
1491 if (output_surface_id != last_output_surface_id_) {
1492 // Resource ids are scoped by the output surface.
1493 // If the originating output surface doesn't match the last one, it
1494 // indicates the renderer's output surface may have been recreated, in which
1495 // case we should recreate the DelegatedRendererLayer, to avoid matching
1496 // resources from the old one with resources from the new one which would
1497 // have the same id. Changing the layer to showing painted content destroys
1498 // the DelegatedRendererLayer.
1499 EvictDelegatedFrame();
1501 // Drop the cc::DelegatedFrameResourceCollection so that we will not return
1502 // any resources from the old output surface with the new output surface id.
1503 if (resource_collection_.get()) {
1504 resource_collection_->SetClient(NULL);
1506 if (resource_collection_->LoseAllResources())
1507 SendReturnedDelegatedResources(last_output_surface_id_);
1509 resource_collection_ = NULL;
1511 last_output_surface_id_ = output_surface_id;
1513 if (frame_size.IsEmpty()) {
1514 DCHECK_EQ(0u, frame_data->resource_list.size());
1515 EvictDelegatedFrame();
1517 if (!resource_collection_) {
1518 resource_collection_ = new cc::DelegatedFrameResourceCollection;
1519 resource_collection_->SetClient(this);
1521 // If the physical frame size changes, we need a new |frame_provider_|. If
1522 // the physical frame size is the same, but the size in DIP changed, we
1523 // need to adjust the scale at which the frames will be drawn, and we do
1524 // this by making a new |frame_provider_| also to ensure the scale change
1525 // is presented in sync with the new frame content.
1526 if (!frame_provider_.get() || frame_size != frame_provider_->frame_size() ||
1527 frame_size_in_dip != current_frame_size_) {
1528 frame_provider_ = new cc::DelegatedFrameProvider(
1529 resource_collection_.get(), frame_data.Pass());
1530 window_->layer()->SetShowDelegatedContent(frame_provider_.get(),
1533 frame_provider_->SetFrameData(frame_data.Pass());
1536 released_front_lock_ = NULL;
1537 current_frame_size_ = frame_size_in_dip;
1540 window_->SchedulePaintInRect(damage_rect_in_dip);
1542 pending_delegated_ack_count_++;
1544 ui::Compositor* compositor = GetCompositor();
1546 SendDelegatedFrameAck(output_surface_id);
1548 for (size_t i = 0; i < latency_info.size(); i++)
1549 compositor->SetLatencyInfo(latency_info[i]);
1550 AddOnCommitCallbackAndDisableLocks(
1551 base::Bind(&RenderWidgetHostViewAura::SendDelegatedFrameAck,
1553 output_surface_id));
1555 DidReceiveFrameFromRenderer();
1556 if (frame_provider_.get())
1557 delegated_frame_evictor_->SwappedFrame(!host_->is_hidden());
1558 // Note: the frame may have been evicted immediately.
1561 void RenderWidgetHostViewAura::SendDelegatedFrameAck(uint32 output_surface_id) {
1562 cc::CompositorFrameAck ack;
1563 if (resource_collection_)
1564 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
1565 RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(),
1567 host_->GetProcess()->GetID(),
1569 DCHECK_GT(pending_delegated_ack_count_, 0);
1570 pending_delegated_ack_count_--;
1573 void RenderWidgetHostViewAura::UnusedResourcesAreAvailable() {
1574 if (pending_delegated_ack_count_)
1577 SendReturnedDelegatedResources(last_output_surface_id_);
1580 void RenderWidgetHostViewAura::SendReturnedDelegatedResources(
1581 uint32 output_surface_id) {
1582 DCHECK(resource_collection_);
1584 cc::CompositorFrameAck ack;
1585 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
1586 DCHECK(!ack.resources.empty());
1588 RenderWidgetHostImpl::SendReclaimCompositorResources(
1589 host_->GetRoutingID(),
1591 host_->GetProcess()->GetID(),
1595 void RenderWidgetHostViewAura::EvictDelegatedFrame() {
1596 window_->layer()->SetShowPaintedContent();
1597 frame_provider_ = NULL;
1598 delegated_frame_evictor_->DiscardedFrame();
1601 void RenderWidgetHostViewAura::SwapSoftwareFrame(
1602 uint32 output_surface_id,
1603 scoped_ptr<cc::SoftwareFrameData> frame_data,
1604 float frame_device_scale_factor,
1605 const std::vector<ui::LatencyInfo>& latency_info) {
1606 const gfx::Size& frame_size = frame_data->size;
1607 const gfx::Rect& damage_rect = frame_data->damage_rect;
1608 gfx::Size frame_size_in_dip =
1609 ConvertSizeToDIP(frame_device_scale_factor, frame_size);
1610 if (ShouldSkipFrame(frame_size_in_dip)) {
1611 ReleaseSoftwareFrame(output_surface_id, frame_data->id);
1612 SendSoftwareFrameAck(output_surface_id);
1616 if (!software_frame_manager_->SwapToNewFrame(
1619 frame_device_scale_factor,
1620 host_->GetProcess()->GetHandle())) {
1621 ReleaseSoftwareFrame(output_surface_id, frame_data->id);
1622 SendSoftwareFrameAck(output_surface_id);
1626 if (last_swapped_surface_size_ != frame_size) {
1627 DLOG_IF(ERROR, damage_rect != gfx::Rect(frame_size))
1628 << "Expected full damage rect";
1630 last_swapped_surface_size_ = frame_size;
1631 last_swapped_surface_scale_factor_ = frame_device_scale_factor;
1633 cc::TextureMailbox mailbox;
1634 scoped_ptr<cc::SingleReleaseCallback> callback;
1635 software_frame_manager_->GetCurrentFrameMailbox(&mailbox, &callback);
1636 DCHECK(mailbox.IsSharedMemory());
1637 current_frame_size_ = frame_size_in_dip;
1639 released_front_lock_ = NULL;
1641 window_->layer()->SetTextureMailbox(mailbox,
1643 frame_device_scale_factor);
1644 window_->SchedulePaintInRect(
1645 ConvertRectToDIP(frame_device_scale_factor, damage_rect));
1647 ui::Compositor* compositor = GetCompositor();
1649 for (size_t i = 0; i < latency_info.size(); i++)
1650 compositor->SetLatencyInfo(latency_info[i]);
1651 AddOnCommitCallbackAndDisableLocks(
1652 base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck,
1654 output_surface_id));
1656 SendSoftwareFrameAck(output_surface_id);
1658 DidReceiveFrameFromRenderer();
1660 software_frame_manager_->SwapToNewFrameComplete(!host_->is_hidden());
1663 void RenderWidgetHostViewAura::SendSoftwareFrameAck(uint32 output_surface_id) {
1664 unsigned software_frame_id = 0;
1665 if (released_software_frame_ &&
1666 released_software_frame_->output_surface_id == output_surface_id) {
1667 software_frame_id = released_software_frame_->frame_id;
1668 released_software_frame_.reset();
1671 cc::CompositorFrameAck ack;
1672 ack.last_software_frame_id = software_frame_id;
1673 RenderWidgetHostImpl::SendSwapCompositorFrameAck(
1674 host_->GetRoutingID(), output_surface_id,
1675 host_->GetProcess()->GetID(), ack);
1676 SendReclaimSoftwareFrames();
1679 void RenderWidgetHostViewAura::SendReclaimSoftwareFrames() {
1680 if (!released_software_frame_)
1682 cc::CompositorFrameAck ack;
1683 ack.last_software_frame_id = released_software_frame_->frame_id;
1684 RenderWidgetHostImpl::SendReclaimCompositorResources(
1685 host_->GetRoutingID(),
1686 released_software_frame_->output_surface_id,
1687 host_->GetProcess()->GetID(),
1689 released_software_frame_.reset();
1692 void RenderWidgetHostViewAura::ReleaseSoftwareFrame(
1693 uint32 output_surface_id,
1694 unsigned software_frame_id) {
1695 SendReclaimSoftwareFrames();
1696 DCHECK(!released_software_frame_);
1697 released_software_frame_.reset(new ReleasedFrameInfo(
1698 output_surface_id, software_frame_id));
1701 void RenderWidgetHostViewAura::OnSwapCompositorFrame(
1702 uint32 output_surface_id,
1703 scoped_ptr<cc::CompositorFrame> frame) {
1704 TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
1705 if (frame->delegated_frame_data) {
1706 SwapDelegatedFrame(output_surface_id,
1707 frame->delegated_frame_data.Pass(),
1708 frame->metadata.device_scale_factor,
1709 frame->metadata.latency_info);
1713 if (frame->software_frame_data) {
1714 SwapSoftwareFrame(output_surface_id,
1715 frame->software_frame_data.Pass(),
1716 frame->metadata.device_scale_factor,
1717 frame->metadata.latency_info);
1721 if (!frame->gl_frame_data || frame->gl_frame_data->mailbox.IsZero())
1724 BufferPresentedCallback ack_callback = base::Bind(
1725 &SendCompositorFrameAck,
1726 host_->GetRoutingID(), output_surface_id, host_->GetProcess()->GetID(),
1727 frame->gl_frame_data->mailbox, frame->gl_frame_data->size);
1729 if (!frame->gl_frame_data->sync_point) {
1730 LOG(ERROR) << "CompositorFrame without sync point. Skipping frame...";
1731 ack_callback.Run(true, scoped_refptr<ui::Texture>());
1735 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
1736 gl_helper->WaitSyncPoint(frame->gl_frame_data->sync_point);
1738 BuffersSwapped(frame->gl_frame_data->size,
1739 frame->gl_frame_data->sub_buffer_rect,
1740 frame->metadata.device_scale_factor,
1741 frame->gl_frame_data->mailbox,
1742 frame->metadata.latency_info,
1747 void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
1748 gfx::NativeViewAccessible accessible_parent) {
1749 if (GetBrowserAccessibilityManager()) {
1750 GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerWin()
1751 ->set_parent_iaccessible(accessible_parent);
1755 gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
1757 if (legacy_render_widget_host_HWND_) {
1758 return reinterpret_cast<gfx::NativeViewId>(
1759 legacy_render_widget_host_HWND_->hwnd());
1765 void RenderWidgetHostViewAura::BuffersSwapped(
1766 const gfx::Size& surface_size,
1767 const gfx::Rect& damage_rect,
1768 float surface_scale_factor,
1769 const gpu::Mailbox& mailbox,
1770 const std::vector<ui::LatencyInfo>& latency_info,
1771 const BufferPresentedCallback& ack_callback) {
1772 scoped_refptr<ui::Texture> previous_texture(current_surface_);
1773 const gfx::Rect surface_rect = gfx::Rect(surface_size);
1774 software_frame_manager_->DiscardCurrentFrame();
1776 if (!SwapBuffersPrepare(surface_rect,
1777 surface_scale_factor,
1784 SkRegion damage(RectToSkIRect(damage_rect));
1785 if (!skipped_damage_.isEmpty()) {
1786 damage.op(skipped_damage_, SkRegion::kUnion_Op);
1787 skipped_damage_.setEmpty();
1790 DCHECK(surface_rect.Contains(SkIRectToRect(damage.getBounds())));
1791 ui::Texture* current_texture = current_surface_.get();
1793 const gfx::Size surface_size_in_pixel = surface_size;
1794 DLOG_IF(ERROR, previous_texture.get() &&
1795 previous_texture->size() != current_texture->size() &&
1796 SkIRectToRect(damage.getBounds()) != surface_rect) <<
1797 "Expected full damage rect after size change";
1798 if (previous_texture.get() && !previous_damage_.isEmpty() &&
1799 previous_texture->size() == current_texture->size()) {
1800 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
1801 GLHelper* gl_helper = factory->GetGLHelper();
1802 gl_helper->CopySubBufferDamage(
1803 current_texture->PrepareTexture(),
1804 previous_texture->PrepareTexture(),
1808 previous_damage_ = damage;
1810 ui::Compositor* compositor = GetCompositor();
1812 // Co-ordinates come in OpenGL co-ordinate space.
1813 // We need to convert to layer space.
1814 gfx::Rect rect_to_paint =
1815 ConvertRectToDIP(surface_scale_factor,
1816 gfx::Rect(damage_rect.x(),
1817 surface_size_in_pixel.height() -
1818 damage_rect.y() - damage_rect.height(),
1819 damage_rect.width(),
1820 damage_rect.height()));
1822 // Damage may not have been DIP aligned, so inflate damage to compensate
1823 // for any round-off error.
1824 rect_to_paint.Inset(-1, -1);
1825 rect_to_paint.Intersect(window_->bounds());
1827 window_->SchedulePaintInRect(rect_to_paint);
1828 for (size_t i = 0; i < latency_info.size(); i++)
1829 compositor->SetLatencyInfo(latency_info[i]);
1832 SwapBuffersCompleted(ack_callback, previous_texture);
1835 void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
1836 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel,
1838 gfx::Rect damage_rect(params_in_pixel.x,
1840 params_in_pixel.width,
1841 params_in_pixel.height);
1842 BufferPresentedCallback ack_callback =
1843 base::Bind(&AcknowledgeBufferForGpu,
1844 params_in_pixel.route_id,
1846 params_in_pixel.mailbox);
1847 BuffersSwapped(params_in_pixel.surface_size,
1849 params_in_pixel.surface_scale_factor,
1850 params_in_pixel.mailbox,
1851 params_in_pixel.latency_info,
1855 void RenderWidgetHostViewAura::AcceleratedSurfaceSuspend() {
1858 void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() {
1859 // This really tells us to release the frontbuffer.
1860 if (current_surface_.get()) {
1861 ui::Compositor* compositor = GetCompositor();
1863 // We need to wait for a commit to clear to guarantee that all we
1864 // will not issue any more GL referencing the previous surface.
1865 AddOnCommitCallbackAndDisableLocks(
1866 base::Bind(&RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor,
1868 current_surface_)); // Hold a ref so the texture will not
1869 // get deleted until after commit.
1871 current_surface_ = NULL;
1872 UpdateExternalTexture();
1876 bool RenderWidgetHostViewAura::HasAcceleratedSurface(
1877 const gfx::Size& desired_size) {
1878 // Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
1879 // matter what is returned here as GetBackingStore is the only caller of this
1880 // method. TODO(jbates) implement this if other Aura code needs it.
1884 void RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor(
1885 scoped_refptr<ui::Texture>) {
1889 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult(
1890 const gfx::Size& dst_size_in_pixel,
1891 const SkBitmap::Config config,
1892 const base::Callback<void(bool, const SkBitmap&)>& callback,
1893 scoped_ptr<cc::CopyOutputResult> result) {
1894 if (result->IsEmpty() || result->size().IsEmpty()) {
1895 callback.Run(false, SkBitmap());
1899 if (result->HasTexture()) {
1900 PrepareTextureCopyOutputResult(dst_size_in_pixel, config,
1906 DCHECK(result->HasBitmap());
1907 PrepareBitmapCopyOutputResult(dst_size_in_pixel, config, callback,
1911 static void CopyFromCompositingSurfaceFinished(
1912 const base::Callback<void(bool, const SkBitmap&)>& callback,
1913 scoped_ptr<cc::SingleReleaseCallback> release_callback,
1914 scoped_ptr<SkBitmap> bitmap,
1915 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
1917 bitmap_pixels_lock.reset();
1919 uint32 sync_point = 0;
1921 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
1922 sync_point = gl_helper->InsertSyncPoint();
1924 bool lost_resource = sync_point == 0;
1925 release_callback->Run(sync_point, lost_resource);
1927 callback.Run(result, *bitmap);
1931 void RenderWidgetHostViewAura::PrepareTextureCopyOutputResult(
1932 const gfx::Size& dst_size_in_pixel,
1933 const SkBitmap::Config config,
1934 const base::Callback<void(bool, const SkBitmap&)>& callback,
1935 scoped_ptr<cc::CopyOutputResult> result) {
1936 DCHECK(result->HasTexture());
1937 base::ScopedClosureRunner scoped_callback_runner(
1938 base::Bind(callback, false, SkBitmap()));
1940 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
1941 bitmap->setConfig(config,
1942 dst_size_in_pixel.width(), dst_size_in_pixel.height(),
1943 0, kOpaque_SkAlphaType);
1944 if (!bitmap->allocPixels())
1947 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
1948 GLHelper* gl_helper = factory->GetGLHelper();
1952 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
1953 new SkAutoLockPixels(*bitmap));
1954 uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
1956 cc::TextureMailbox texture_mailbox;
1957 scoped_ptr<cc::SingleReleaseCallback> release_callback;
1958 result->TakeTexture(&texture_mailbox, &release_callback);
1959 DCHECK(texture_mailbox.IsTexture());
1960 if (!texture_mailbox.IsTexture())
1963 ignore_result(scoped_callback_runner.Release());
1965 gl_helper->CropScaleReadbackAndCleanMailbox(
1966 texture_mailbox.mailbox(),
1967 texture_mailbox.sync_point(),
1969 gfx::Rect(result->size()),
1973 base::Bind(&CopyFromCompositingSurfaceFinished,
1975 base::Passed(&release_callback),
1976 base::Passed(&bitmap),
1977 base::Passed(&bitmap_pixels_lock)));
1981 void RenderWidgetHostViewAura::PrepareBitmapCopyOutputResult(
1982 const gfx::Size& dst_size_in_pixel,
1983 const SkBitmap::Config config,
1984 const base::Callback<void(bool, const SkBitmap&)>& callback,
1985 scoped_ptr<cc::CopyOutputResult> result) {
1986 if (config != SkBitmap::kARGB_8888_Config) {
1988 callback.Run(false, SkBitmap());
1991 DCHECK(result->HasBitmap());
1992 base::ScopedClosureRunner scoped_callback_runner(
1993 base::Bind(callback, false, SkBitmap()));
1995 scoped_ptr<SkBitmap> source = result->TakeBitmap();
2000 ignore_result(scoped_callback_runner.Release());
2002 SkBitmap bitmap = skia::ImageOperations::Resize(
2004 skia::ImageOperations::RESIZE_BEST,
2005 dst_size_in_pixel.width(),
2006 dst_size_in_pixel.height());
2007 callback.Run(true, bitmap);
2011 void RenderWidgetHostViewAura::ReturnSubscriberTexture(
2012 base::WeakPtr<RenderWidgetHostViewAura> rwhva,
2013 scoped_refptr<OwnedMailbox> subscriber_texture,
2014 uint32 sync_point) {
2015 if (!subscriber_texture.get())
2020 rwhva->active_frame_subscriber_textures_.count(subscriber_texture.get()),
2023 subscriber_texture->UpdateSyncPoint(sync_point);
2025 rwhva->active_frame_subscriber_textures_.erase(subscriber_texture.get());
2026 if (rwhva->frame_subscriber_ && subscriber_texture->texture_id())
2027 rwhva->idle_frame_subscriber_textures_.push_back(subscriber_texture);
2030 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinishedForVideo(
2031 base::WeakPtr<RenderWidgetHostViewAura> rwhva,
2032 const base::Callback<void(bool)>& callback,
2033 scoped_refptr<OwnedMailbox> subscriber_texture,
2034 scoped_ptr<cc::SingleReleaseCallback> release_callback,
2036 callback.Run(result);
2038 uint32 sync_point = 0;
2040 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
2041 sync_point = gl_helper->InsertSyncPoint();
2043 if (release_callback) {
2044 // A release callback means the texture came from the compositor, so there
2045 // should be no |subscriber_texture|.
2046 DCHECK(!subscriber_texture);
2047 bool lost_resource = sync_point == 0;
2048 release_callback->Run(sync_point, lost_resource);
2050 ReturnSubscriberTexture(rwhva, subscriber_texture, sync_point);
2054 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo(
2055 base::WeakPtr<RenderWidgetHostViewAura> rwhva,
2056 scoped_refptr<OwnedMailbox> subscriber_texture,
2057 scoped_refptr<media::VideoFrame> video_frame,
2058 const base::Callback<void(bool)>& callback,
2059 scoped_ptr<cc::CopyOutputResult> result) {
2060 base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
2061 base::ScopedClosureRunner scoped_return_subscriber_texture(
2062 base::Bind(&ReturnSubscriberTexture, rwhva, subscriber_texture, 0));
2066 if (result->IsEmpty())
2068 if (result->size().IsEmpty())
2071 // Compute the dest size we want after the letterboxing resize. Make the
2072 // coordinates and sizes even because we letterbox in YUV space
2073 // (see CopyRGBToVideoFrame). They need to be even for the UV samples to
2074 // line up correctly.
2075 // The video frame's coded_size() and the result's size() are both physical
2077 gfx::Rect region_in_frame =
2078 media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()),
2080 region_in_frame = gfx::Rect(region_in_frame.x() & ~1,
2081 region_in_frame.y() & ~1,
2082 region_in_frame.width() & ~1,
2083 region_in_frame.height() & ~1);
2084 if (region_in_frame.IsEmpty())
2087 if (!result->HasTexture()) {
2088 DCHECK(result->HasBitmap());
2089 scoped_ptr<SkBitmap> bitmap = result->TakeBitmap();
2090 // Scale the bitmap to the required size, if necessary.
2091 SkBitmap scaled_bitmap;
2092 if (result->size().width() != region_in_frame.width() ||
2093 result->size().height() != region_in_frame.height()) {
2094 skia::ImageOperations::ResizeMethod method =
2095 skia::ImageOperations::RESIZE_GOOD;
2096 scaled_bitmap = skia::ImageOperations::Resize(*bitmap.get(), method,
2097 region_in_frame.width(),
2098 region_in_frame.height());
2100 scaled_bitmap = *bitmap.get();
2104 SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap);
2106 media::CopyRGBToVideoFrame(
2107 reinterpret_cast<uint8*>(scaled_bitmap.getPixels()),
2108 scaled_bitmap.rowBytes(),
2112 ignore_result(scoped_callback_runner.Release());
2117 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
2118 GLHelper* gl_helper = factory->GetGLHelper();
2121 if (subscriber_texture.get() && !subscriber_texture->texture_id())
2124 cc::TextureMailbox texture_mailbox;
2125 scoped_ptr<cc::SingleReleaseCallback> release_callback;
2126 result->TakeTexture(&texture_mailbox, &release_callback);
2127 DCHECK(texture_mailbox.IsTexture());
2128 if (!texture_mailbox.IsTexture())
2131 gfx::Rect result_rect(result->size());
2133 content::ReadbackYUVInterface* yuv_readback_pipeline =
2134 rwhva->yuv_readback_pipeline_.get();
2135 if (yuv_readback_pipeline == NULL ||
2136 yuv_readback_pipeline->scaler()->SrcSize() != result_rect.size() ||
2137 yuv_readback_pipeline->scaler()->SrcSubrect() != result_rect ||
2138 yuv_readback_pipeline->scaler()->DstSize() != region_in_frame.size()) {
2139 GLHelper::ScalerQuality quality = GLHelper::SCALER_QUALITY_FAST;
2140 std::string quality_switch = switches::kTabCaptureDownscaleQuality;
2141 // If we're scaling up, we can use the "best" quality.
2142 if (result_rect.size().width() < region_in_frame.size().width() &&
2143 result_rect.size().height() < region_in_frame.size().height())
2144 quality_switch = switches::kTabCaptureUpscaleQuality;
2146 std::string switch_value =
2147 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(quality_switch);
2148 if (switch_value == "fast")
2149 quality = GLHelper::SCALER_QUALITY_FAST;
2150 else if (switch_value == "good")
2151 quality = GLHelper::SCALER_QUALITY_GOOD;
2152 else if (switch_value == "best")
2153 quality = GLHelper::SCALER_QUALITY_BEST;
2155 rwhva->yuv_readback_pipeline_.reset(
2156 gl_helper->CreateReadbackPipelineYUV(quality,
2159 video_frame->coded_size(),
2163 yuv_readback_pipeline = rwhva->yuv_readback_pipeline_.get();
2166 ignore_result(scoped_callback_runner.Release());
2167 ignore_result(scoped_return_subscriber_texture.Release());
2168 base::Callback<void(bool result)> finished_callback = base::Bind(
2169 &RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinishedForVideo,
2173 base::Passed(&release_callback));
2174 yuv_readback_pipeline->ReadbackYUV(texture_mailbox.mailbox(),
2175 texture_mailbox.sync_point(),
2180 void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) {
2181 GetScreenInfoForWindow(results, window_->GetRootWindow() ? window_ : NULL);
2184 gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
2186 // aura::Window::GetBoundsInScreen doesn't take non-client area into
2188 RECT window_rect = {0};
2190 aura::Window* top_level = window_->GetToplevelWindow();
2191 aura::WindowTreeHost* host = top_level->GetHost();
2193 return top_level->GetBoundsInScreen();
2194 HWND hwnd = host->GetAcceleratedWidget();
2195 ::GetWindowRect(hwnd, &window_rect);
2196 gfx::Rect rect(window_rect);
2198 // Maximized windows are outdented from the work area by the frame thickness
2199 // even though this "frame" is not painted. This confuses code (and people)
2200 // that think of a maximized window as corresponding exactly to the work area.
2201 // Correct for this by subtracting the frame thickness back off.
2202 if (::IsZoomed(hwnd)) {
2203 rect.Inset(GetSystemMetrics(SM_CXSIZEFRAME),
2204 GetSystemMetrics(SM_CYSIZEFRAME));
2207 return gfx::win::ScreenToDIPRect(rect);
2209 return window_->GetToplevelWindow()->GetBoundsInScreen();
2213 void RenderWidgetHostViewAura::GestureEventAck(
2214 const blink::WebGestureEvent& event,
2215 InputEventAckState ack_result) {
2216 if (touch_editing_client_)
2217 touch_editing_client_->GestureEventAck(event.type);
2220 void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
2221 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
2222 ScopedVector<ui::TouchEvent> events;
2223 if (!MakeUITouchEventsFromWebTouchEvents(touch, &events,
2224 SCREEN_COORDINATES))
2227 aura::WindowTreeHost* host = window_->GetHost();
2228 // |host| is NULL during tests.
2232 ui::EventResult result = (ack_result ==
2233 INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
2234 for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
2235 end = events.end(); iter != end; ++iter) {
2236 host->dispatcher()->ProcessedTouchEvent((*iter), window_, result);
2240 scoped_ptr<SyntheticGestureTarget>
2241 RenderWidgetHostViewAura::CreateSyntheticGestureTarget() {
2242 return scoped_ptr<SyntheticGestureTarget>(
2243 new SyntheticGestureTargetAura(host_));
2246 void RenderWidgetHostViewAura::SetHasHorizontalScrollbar(
2247 bool has_horizontal_scrollbar) {
2248 // Not needed. Mac-only.
2251 void RenderWidgetHostViewAura::SetScrollOffsetPinning(
2252 bool is_pinned_to_left, bool is_pinned_to_right) {
2253 // Not needed. Mac-only.
2256 void RenderWidgetHostViewAura::CreateBrowserAccessibilityManagerIfNeeded() {
2257 if (GetBrowserAccessibilityManager())
2260 BrowserAccessibilityManager* manager = NULL;
2262 aura::WindowTreeHost* host = window_->GetHost();
2265 HWND hwnd = host->GetAcceleratedWidget();
2267 // The accessible_parent may be NULL at this point. The WebContents will pass
2268 // it down to this instance (by way of the RenderViewHost and
2269 // RenderWidgetHost) when it is known. This instance will then set it on its
2270 // BrowserAccessibilityManager.
2271 gfx::NativeViewAccessible accessible_parent =
2272 host_->GetParentNativeViewAccessible();
2274 if (legacy_render_widget_host_HWND_) {
2275 manager = new BrowserAccessibilityManagerWin(
2276 legacy_render_widget_host_HWND_.get(), accessible_parent,
2277 BrowserAccessibilityManagerWin::GetEmptyDocument(), this);
2280 manager = BrowserAccessibilityManager::Create(
2281 BrowserAccessibilityManager::GetEmptyDocument(), this);
2283 SetBrowserAccessibilityManager(manager);
2286 gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
2287 return ImageTransportFactory::GetInstance()->GetSharedSurfaceHandle();
2290 bool RenderWidgetHostViewAura::LockMouse() {
2291 aura::Window* root_window = window_->GetRootWindow();
2298 mouse_locked_ = true;
2299 #if !defined(OS_WIN)
2300 window_->SetCapture();
2302 UpdateMouseLockRegion();
2304 aura::client::CursorClient* cursor_client =
2305 aura::client::GetCursorClient(root_window);
2306 if (cursor_client) {
2307 cursor_client->HideCursor();
2308 cursor_client->LockCursor();
2311 if (ShouldMoveToCenter()) {
2312 synthetic_move_sent_ = true;
2313 window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
2315 tooltip_disabler_.reset(new aura::client::ScopedTooltipDisabler(root_window));
2319 void RenderWidgetHostViewAura::UnlockMouse() {
2320 tooltip_disabler_.reset();
2322 aura::Window* root_window = window_->GetRootWindow();
2323 if (!mouse_locked_ || !root_window)
2326 mouse_locked_ = false;
2328 #if !defined(OS_WIN)
2329 window_->ReleaseCapture();
2333 window_->MoveCursorTo(unlocked_mouse_position_);
2334 aura::client::CursorClient* cursor_client =
2335 aura::client::GetCursorClient(root_window);
2336 if (cursor_client) {
2337 cursor_client->UnlockCursor();
2338 cursor_client->ShowCursor();
2341 host_->LostMouseLock();
2344 ////////////////////////////////////////////////////////////////////////////////
2345 // RenderWidgetHostViewAura, ui::TextInputClient implementation:
2346 void RenderWidgetHostViewAura::SetCompositionText(
2347 const ui::CompositionText& composition) {
2351 // ui::CompositionUnderline should be identical to
2352 // blink::WebCompositionUnderline, so that we can do reinterpret_cast safely.
2353 COMPILE_ASSERT(sizeof(ui::CompositionUnderline) ==
2354 sizeof(blink::WebCompositionUnderline),
2355 ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
2357 // TODO(suzhe): convert both renderer_host and renderer to use
2358 // ui::CompositionText.
2359 const std::vector<blink::WebCompositionUnderline>& underlines =
2360 reinterpret_cast<const std::vector<blink::WebCompositionUnderline>&>(
2361 composition.underlines);
2363 // TODO(suzhe): due to a bug of webkit, we can't use selection range with
2364 // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
2365 host_->ImeSetComposition(composition.text, underlines,
2366 composition.selection.end(),
2367 composition.selection.end());
2369 has_composition_text_ = !composition.text.empty();
2372 void RenderWidgetHostViewAura::ConfirmCompositionText() {
2373 if (host_ && has_composition_text_) {
2374 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
2377 has_composition_text_ = false;
2380 void RenderWidgetHostViewAura::ClearCompositionText() {
2381 if (host_ && has_composition_text_)
2382 host_->ImeCancelComposition();
2383 has_composition_text_ = false;
2386 void RenderWidgetHostViewAura::InsertText(const base::string16& text) {
2387 DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
2389 host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false);
2390 has_composition_text_ = false;
2393 void RenderWidgetHostViewAura::InsertChar(base::char16 ch, int flags) {
2394 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
2395 popup_child_host_view_->InsertChar(ch, flags);
2399 // Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547
2400 if (host_ && (accept_return_character_ || ch != ui::VKEY_RETURN)) {
2401 double now = ui::EventTimeForNow().InSecondsF();
2402 // Send a blink::WebInputEvent::Char event to |host_|.
2403 NativeWebKeyboardEvent webkit_event(ui::ET_KEY_PRESSED,
2408 host_->ForwardKeyboardEvent(webkit_event);
2412 gfx::NativeWindow RenderWidgetHostViewAura::GetAttachedWindow() const {
2416 ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const {
2417 return text_input_type_;
2420 ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
2421 return text_input_mode_;
2424 bool RenderWidgetHostViewAura::CanComposeInline() const {
2425 return can_compose_inline_;
2428 gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(
2429 const gfx::Rect& rect) const {
2430 gfx::Point origin = rect.origin();
2431 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
2433 aura::Window* root_window = window_->GetRootWindow();
2436 aura::client::ScreenPositionClient* screen_position_client =
2437 aura::client::GetScreenPositionClient(root_window);
2438 if (!screen_position_client)
2440 screen_position_client->ConvertPointToScreen(window_, &origin);
2441 screen_position_client->ConvertPointToScreen(window_, &end);
2442 return gfx::Rect(origin.x(),
2444 end.x() - origin.x(),
2445 end.y() - origin.y());
2448 gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
2449 const gfx::Rect& rect) const {
2450 gfx::Point origin = rect.origin();
2451 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
2453 aura::Window* root_window = window_->GetRootWindow();
2455 aura::client::ScreenPositionClient* screen_position_client =
2456 aura::client::GetScreenPositionClient(root_window);
2457 screen_position_client->ConvertPointFromScreen(window_, &origin);
2458 screen_position_client->ConvertPointFromScreen(window_, &end);
2459 return gfx::Rect(origin.x(),
2461 end.x() - origin.x(),
2462 end.y() - origin.y());
2468 gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const {
2469 const gfx::Rect rect =
2470 gfx::UnionRects(selection_anchor_rect_, selection_focus_rect_);
2471 return ConvertRectToScreen(rect);
2474 bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(
2476 gfx::Rect* rect) const {
2478 if (index >= composition_character_bounds_.size())
2480 *rect = ConvertRectToScreen(composition_character_bounds_[index]);
2484 bool RenderWidgetHostViewAura::HasCompositionText() const {
2485 return has_composition_text_;
2488 bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) const {
2489 range->set_start(selection_text_offset_);
2490 range->set_end(selection_text_offset_ + selection_text_.length());
2494 bool RenderWidgetHostViewAura::GetCompositionTextRange(
2495 gfx::Range* range) const {
2496 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
2501 bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) const {
2502 range->set_start(selection_range_.start());
2503 range->set_end(selection_range_.end());
2507 bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) {
2508 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
2513 bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) {
2514 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
2519 bool RenderWidgetHostViewAura::GetTextFromRange(
2520 const gfx::Range& range,
2521 base::string16* text) const {
2522 gfx::Range selection_text_range(selection_text_offset_,
2523 selection_text_offset_ + selection_text_.length());
2525 if (!selection_text_range.Contains(range)) {
2529 if (selection_text_range.EqualsIgnoringDirection(range)) {
2530 // Avoid calling substr whose performance is low.
2531 *text = selection_text_;
2533 *text = selection_text_.substr(
2534 range.GetMin() - selection_text_offset_,
2540 void RenderWidgetHostViewAura::OnInputMethodChanged() {
2544 if (GetInputMethod())
2545 host_->SetInputMethodActive(GetInputMethod()->IsActive());
2547 // TODO(suzhe): implement the newly added “locale” property of HTML DOM
2551 bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
2552 base::i18n::TextDirection direction) {
2555 host_->UpdateTextDirection(
2556 direction == base::i18n::RIGHT_TO_LEFT ?
2557 blink::WebTextDirectionRightToLeft :
2558 blink::WebTextDirectionLeftToRight);
2559 host_->NotifyTextDirection();
2563 void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
2564 size_t before, size_t after) {
2565 RenderFrameHostImpl* rfh = GetFocusedFrame();
2567 rfh->ExtendSelectionAndDelete(before, after);
2570 void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
2571 gfx::Rect intersected_rect(
2572 gfx::IntersectRects(rect, window_->GetBoundsInScreen()));
2574 if (intersected_rect.IsEmpty())
2577 host_->ScrollFocusedEditableNodeIntoRect(
2578 ConvertRectFromScreen(intersected_rect));
2581 void RenderWidgetHostViewAura::OnCandidateWindowShown() {
2582 host_->CandidateWindowShown();
2585 void RenderWidgetHostViewAura::OnCandidateWindowUpdated() {
2586 host_->CandidateWindowUpdated();
2589 void RenderWidgetHostViewAura::OnCandidateWindowHidden() {
2590 host_->CandidateWindowHidden();
2593 ////////////////////////////////////////////////////////////////////////////////
2594 // RenderWidgetHostViewAura, gfx::DisplayObserver implementation:
2596 void RenderWidgetHostViewAura::OnDisplayBoundsChanged(
2597 const gfx::Display& display) {
2598 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
2599 if (display.id() == screen->GetDisplayNearestWindow(window_).id()) {
2600 UpdateScreenInfo(window_);
2601 current_cursor_.SetDisplayInfo(display);
2602 UpdateCursorIfOverSelf();
2606 void RenderWidgetHostViewAura::OnDisplayAdded(
2607 const gfx::Display& new_display) {
2610 void RenderWidgetHostViewAura::OnDisplayRemoved(
2611 const gfx::Display& old_display) {
2614 ////////////////////////////////////////////////////////////////////////////////
2615 // RenderWidgetHostViewAura, aura::WindowDelegate implementation:
2617 gfx::Size RenderWidgetHostViewAura::GetMinimumSize() const {
2621 gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const {
2625 void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
2626 const gfx::Rect& new_bounds) {
2627 base::AutoReset<bool> in_bounds_changed(&in_bounds_changed_, true);
2628 // We care about this whenever RenderWidgetHostViewAura is not owned by a
2629 // WebContentsViewAura since changes to the Window's bounds need to be
2630 // messaged to the renderer. WebContentsViewAura invokes SetSize() or
2631 // SetBounds() itself. No matter how we got here, any redundant calls are
2633 SetSize(new_bounds.size());
2636 gfx::NativeCursor RenderWidgetHostViewAura::GetCursor(const gfx::Point& point) {
2638 return ui::kCursorNone;
2639 return current_cursor_.GetNativeCursor();
2642 int RenderWidgetHostViewAura::GetNonClientComponent(
2643 const gfx::Point& point) const {
2647 bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
2648 aura::Window* child,
2649 const gfx::Point& location) {
2653 bool RenderWidgetHostViewAura::CanFocus() {
2654 return popup_type_ == blink::WebPopupTypeNone;
2657 void RenderWidgetHostViewAura::OnCaptureLost() {
2658 host_->LostCapture();
2659 if (touch_editing_client_)
2660 touch_editing_client_->EndTouchEditing(false);
2663 void RenderWidgetHostViewAura::OnPaint(gfx::Canvas* canvas) {
2664 bool has_backing_store = !!host_->GetBackingStore(false);
2665 if (has_backing_store) {
2666 paint_canvas_ = canvas;
2667 BackingStoreAura* backing_store = static_cast<BackingStoreAura*>(
2668 host_->GetBackingStore(true));
2669 paint_canvas_ = NULL;
2670 backing_store->SkiaShowRect(gfx::Point(), canvas);
2672 ui::Compositor* compositor = GetCompositor();
2674 for (size_t i = 0; i < software_latency_info_.size(); i++)
2675 compositor->SetLatencyInfo(software_latency_info_[i]);
2677 software_latency_info_.clear();
2679 // For non-opaque windows, we don't draw anything, since we depend on the
2680 // canvas coming from the compositor to already be initialized as
2682 if (window_->layer()->fills_bounds_opaquely())
2683 canvas->DrawColor(SK_ColorWHITE);
2687 void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
2688 float device_scale_factor) {
2692 BackingStoreAura* backing_store = static_cast<BackingStoreAura*>(
2693 host_->GetBackingStore(false));
2694 if (backing_store) // NULL in hardware path.
2695 backing_store->ScaleFactorChanged(device_scale_factor);
2697 UpdateScreenInfo(window_);
2699 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
2700 GetDisplayNearestWindow(window_);
2701 DCHECK_EQ(device_scale_factor, display.device_scale_factor());
2702 current_cursor_.SetDisplayInfo(display);
2705 void RenderWidgetHostViewAura::OnWindowDestroying(aura::Window* window) {
2708 // If the tab was hidden and it's closed, host_->is_hidden would have been
2709 // reset to false in RenderWidgetHostImpl::RendererExited.
2710 if (!window_->GetRootWindow() || host_->is_hidden()) {
2711 parent = ui::GetHiddenWindow();
2713 parent = window_->GetHost()->GetAcceleratedWidget();
2715 LPARAM lparam = reinterpret_cast<LPARAM>(this);
2716 EnumChildWindows(parent, WindowDestroyingCallback, lparam);
2719 // Make sure that the input method no longer references to this object before
2720 // this object is removed from the root window (i.e. this object loses access
2721 // to the input method).
2722 ui::InputMethod* input_method = GetInputMethod();
2724 input_method->DetachTextInputClient(this);
2727 void RenderWidgetHostViewAura::OnWindowDestroyed(aura::Window* window) {
2728 host_->ViewDestroyed();
2732 void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible) {
2735 bool RenderWidgetHostViewAura::HasHitTestMask() const {
2739 void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
2742 ////////////////////////////////////////////////////////////////////////////////
2743 // RenderWidgetHostViewAura, ui::EventHandler implementation:
2745 void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
2746 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent");
2747 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2750 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
2751 popup_child_host_view_->OnKeyEvent(event);
2752 if (event->handled())
2756 // We need to handle the Escape key for Pepper Flash.
2757 if (is_fullscreen_ && event->key_code() == ui::VKEY_ESCAPE) {
2758 // Focus the window we were created from.
2759 if (host_tracker_.get() && !host_tracker_->windows().empty()) {
2760 aura::Window* host = *(host_tracker_->windows().begin());
2761 aura::client::FocusClient* client = aura::client::GetFocusClient(host);
2763 // Calling host->Focus() may delete |this|. We create a local observer
2764 // for that. In that case we exit without further access to any members.
2765 aura::WindowTracker tracker;
2766 aura::Window* window = window_;
2767 tracker.Add(window);
2769 if (!tracker.Contains(window)) {
2770 event->SetHandled();
2775 if (!in_shutdown_) {
2776 in_shutdown_ = true;
2780 if (event->key_code() == ui::VKEY_RETURN) {
2781 // Do not forward return key release events if no press event was handled.
2782 if (event->type() == ui::ET_KEY_RELEASED && !accept_return_character_)
2784 // Accept return key character events between press and release events.
2785 accept_return_character_ = event->type() == ui::ET_KEY_PRESSED;
2788 // We don't have to communicate with an input method here.
2789 if (!event->HasNativeEvent()) {
2790 NativeWebKeyboardEvent webkit_event(
2793 event->is_char() ? event->GetCharacter() : event->key_code(),
2795 ui::EventTimeForNow().InSecondsF());
2796 host_->ForwardKeyboardEvent(webkit_event);
2798 NativeWebKeyboardEvent webkit_event(event);
2799 host_->ForwardKeyboardEvent(webkit_event);
2802 event->SetHandled();
2805 void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
2806 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
2808 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2811 if (mouse_locked_) {
2812 aura::client::CursorClient* cursor_client =
2813 aura::client::GetCursorClient(window_->GetRootWindow());
2814 DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
2816 if (event->type() == ui::ET_MOUSEWHEEL) {
2817 blink::WebMouseWheelEvent mouse_wheel_event =
2818 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
2819 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
2820 host_->ForwardWheelEvent(mouse_wheel_event);
2824 gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
2826 // If we receive non client mouse messages while we are in the locked state
2827 // it probably means that the mouse left the borders of our window and
2828 // needs to be moved back to the center.
2829 if (event->flags() & ui::EF_IS_NON_CLIENT) {
2830 synthetic_move_sent_ = true;
2831 window_->MoveCursorTo(center);
2835 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
2837 bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED ||
2838 event->type() == ui::ET_MOUSE_DRAGGED) &&
2839 mouse_event.x == center.x() && mouse_event.y == center.y();
2841 ModifyEventMovementAndCoords(&mouse_event);
2843 bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
2844 if (should_not_forward) {
2845 synthetic_move_sent_ = false;
2847 // Check if the mouse has reached the border and needs to be centered.
2848 if (ShouldMoveToCenter()) {
2849 synthetic_move_sent_ = true;
2850 window_->MoveCursorTo(center);
2852 // Forward event to renderer.
2853 if (CanRendererHandleEvent(event) &&
2854 !(event->flags() & ui::EF_FROM_TOUCH)) {
2855 host_->ForwardMouseEvent(mouse_event);
2856 // Ensure that we get keyboard focus on mouse down as a plugin window
2857 // may have grabbed keyboard focus.
2858 if (event->type() == ui::ET_MOUSE_PRESSED)
2865 // As the overscroll is handled during scroll events from the trackpad, the
2866 // RWHVA window is transformed by the overscroll controller. This transform
2867 // triggers a synthetic mouse-move event to be generated (by the aura
2868 // RootWindow). But this event interferes with the overscroll gesture. So,
2869 // ignore such synthetic mouse-move events if an overscroll gesture is in
2871 if (host_->overscroll_controller() &&
2872 host_->overscroll_controller()->overscroll_mode() != OVERSCROLL_NONE &&
2873 event->flags() & ui::EF_IS_SYNTHESIZED &&
2874 (event->type() == ui::ET_MOUSE_ENTERED ||
2875 event->type() == ui::ET_MOUSE_EXITED ||
2876 event->type() == ui::ET_MOUSE_MOVED)) {
2877 event->StopPropagation();
2881 if (event->type() == ui::ET_MOUSEWHEEL) {
2883 // We get mouse wheel/scroll messages even if we are not in the foreground.
2884 // So here we check if we have any owned popup windows in the foreground and
2886 aura::WindowTreeHost* host = window_->GetHost();
2888 HWND parent = host->GetAcceleratedWidget();
2889 HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
2890 EnumThreadWindows(GetCurrentThreadId(),
2892 reinterpret_cast<LPARAM>(toplevel_hwnd));
2895 blink::WebMouseWheelEvent mouse_wheel_event =
2896 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
2897 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
2898 host_->ForwardWheelEvent(mouse_wheel_event);
2899 } else if (CanRendererHandleEvent(event) &&
2900 !(event->flags() & ui::EF_FROM_TOUCH)) {
2901 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
2902 ModifyEventMovementAndCoords(&mouse_event);
2903 host_->ForwardMouseEvent(mouse_event);
2904 // Ensure that we get keyboard focus on mouse down as a plugin window may
2905 // have grabbed keyboard focus.
2906 if (event->type() == ui::ET_MOUSE_PRESSED)
2910 switch (event->type()) {
2911 case ui::ET_MOUSE_PRESSED:
2912 window_->SetCapture();
2913 // Confirm existing composition text on mouse click events, to make sure
2914 // the input caret won't be moved with an ongoing composition text.
2915 FinishImeCompositionSession();
2917 case ui::ET_MOUSE_RELEASED:
2918 window_->ReleaseCapture();
2924 // Needed to propagate mouse event to |window_->parent()->delegate()|, but
2925 // note that it might be something other than a WebContentsViewAura instance.
2926 // TODO(pkotwicz): Find a better way of doing this.
2927 // In fullscreen mode which is typically used by flash, don't forward
2928 // the mouse events to the parent. The renderer and the plugin process
2929 // handle these events.
2930 if (!is_fullscreen_ && window_->parent()->delegate() &&
2931 !(event->flags() & ui::EF_FROM_TOUCH)) {
2932 event->ConvertLocationToTarget(window_, window_->parent());
2933 window_->parent()->delegate()->OnMouseEvent(event);
2936 if (!IsXButtonUpEvent(event))
2937 event->SetHandled();
2940 void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
2941 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
2942 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2945 if (event->type() == ui::ET_SCROLL) {
2946 #if !defined(OS_WIN)
2948 // Investigate if this is true for Windows 8 Metro ASH as well.
2949 if (event->finger_count() != 2)
2952 blink::WebGestureEvent gesture_event =
2953 MakeWebGestureEventFlingCancel();
2954 host_->ForwardGestureEvent(gesture_event);
2955 blink::WebMouseWheelEvent mouse_wheel_event =
2956 MakeWebMouseWheelEvent(event);
2957 host_->ForwardWheelEvent(mouse_wheel_event);
2958 RecordAction(base::UserMetricsAction("TrackpadScroll"));
2959 } else if (event->type() == ui::ET_SCROLL_FLING_START ||
2960 event->type() == ui::ET_SCROLL_FLING_CANCEL) {
2961 blink::WebGestureEvent gesture_event =
2962 MakeWebGestureEvent(event);
2963 host_->ForwardGestureEvent(gesture_event);
2964 if (event->type() == ui::ET_SCROLL_FLING_START)
2965 RecordAction(base::UserMetricsAction("TrackpadScrollFling"));
2968 event->SetHandled();
2971 void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
2972 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent");
2973 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2976 // Update the touch event first.
2977 blink::WebTouchPoint* point = UpdateWebTouchEventFromUIEvent(*event,
2980 // Forward the touch event only if a touch point was updated, and there's a
2981 // touch-event handler in the page, and no other touch-event is in the queue.
2982 // It is important to always consume the event if there is a touch-event
2983 // handler in the page, or some touch-event is already in the queue, even if
2984 // no point has been updated, to make sure that this event does not get
2985 // processed by the gesture recognizer before the events in the queue.
2986 if (host_->ShouldForwardTouchEvent())
2987 event->StopPropagation();
2990 if (host_->ShouldForwardTouchEvent())
2991 host_->ForwardTouchEventWithLatencyInfo(touch_event_, *event->latency());
2992 UpdateWebTouchEventAfterDispatch(&touch_event_, point);
2996 void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
2997 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent");
2998 if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN ||
2999 event->type() == ui::ET_GESTURE_PINCH_UPDATE ||
3000 event->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) {
3001 event->SetHandled();
3005 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
3008 RenderViewHostDelegate* delegate = NULL;
3009 if (host_->IsRenderView())
3010 delegate = RenderViewHost::From(host_)->GetDelegate();
3012 if (delegate && event->type() == ui::ET_GESTURE_BEGIN &&
3013 event->details().touch_points() == 1) {
3014 delegate->HandleGestureBegin();
3017 blink::WebGestureEvent gesture = MakeWebGestureEvent(event);
3018 if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
3019 // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
3020 // event to stop any in-progress flings.
3021 blink::WebGestureEvent fling_cancel = gesture;
3022 fling_cancel.type = blink::WebInputEvent::GestureFlingCancel;
3023 fling_cancel.sourceDevice = blink::WebGestureEvent::Touchscreen;
3024 host_->ForwardGestureEvent(fling_cancel);
3027 if (gesture.type != blink::WebInputEvent::Undefined) {
3028 host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
3030 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
3031 event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
3032 event->type() == ui::ET_GESTURE_SCROLL_END) {
3033 RecordAction(base::UserMetricsAction("TouchscreenScroll"));
3034 } else if (event->type() == ui::ET_SCROLL_FLING_START) {
3035 RecordAction(base::UserMetricsAction("TouchscreenScrollFling"));
3039 if (delegate && event->type() == ui::ET_GESTURE_END &&
3040 event->details().touch_points() == 1) {
3041 delegate->HandleGestureEnd();
3044 // If a gesture is not processed by the webpage, then WebKit processes it
3045 // (e.g. generates synthetic mouse events).
3046 event->SetHandled();
3049 ////////////////////////////////////////////////////////////////////////////////
3050 // RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation:
3052 bool RenderWidgetHostViewAura::ShouldActivate() const {
3053 aura::WindowTreeHost* host = window_->GetHost();
3056 const ui::Event* event = host->dispatcher()->current_event();
3059 return is_fullscreen_;
3062 ////////////////////////////////////////////////////////////////////////////////
3063 // RenderWidgetHostViewAura,
3064 // aura::client::ActivationChangeObserver implementation:
3066 void RenderWidgetHostViewAura::OnWindowActivated(aura::Window* gained_active,
3067 aura::Window* lost_active) {
3068 DCHECK(window_ == gained_active || window_ == lost_active);
3069 if (window_ == gained_active) {
3070 const ui::Event* event = window_->GetHost()->dispatcher()->current_event();
3071 if (event && PointerEventActivates(*event))
3072 host_->OnPointerEventActivate();
3076 ////////////////////////////////////////////////////////////////////////////////
3077 // RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation:
3079 void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible) {
3080 NotifyRendererOfCursorVisibilityState(is_visible);
3083 ////////////////////////////////////////////////////////////////////////////////
3084 // RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation:
3086 void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
3087 aura::Window* lost_focus) {
3088 DCHECK(window_ == gained_focus || window_ == lost_focus);
3089 if (window_ == gained_focus) {
3090 // We need to honor input bypass if the associated tab is does not want
3091 // input. This gives the current focused window a chance to be the text
3092 // input client and handle events.
3093 if (host_->ignore_input_events())
3097 host_->SetActive(true);
3099 ui::InputMethod* input_method = GetInputMethod();
3101 // Ask the system-wide IME to send all TextInputClient messages to |this|
3103 input_method->SetFocusedTextInputClient(this);
3104 host_->SetInputMethodActive(input_method->IsActive());
3106 // Often the application can set focus to the view in response to a key
3107 // down. However the following char event shouldn't be sent to the web
3109 host_->SuppressNextCharEvents();
3111 host_->SetInputMethodActive(false);
3113 } else if (window_ == lost_focus) {
3114 host_->SetActive(false);
3117 DetachFromInputMethod();
3118 host_->SetInputMethodActive(false);
3120 if (touch_editing_client_)
3121 touch_editing_client_->EndTouchEditing(false);
3123 // If we lose the focus while fullscreen, close the window; Pepper Flash
3124 // won't do it for us (unlike NPAPI Flash). However, we do not close the
3125 // window if we lose the focus to a window on another display.
3126 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
3127 bool focusing_other_display =
3128 gained_focus && screen->GetNumDisplays() > 1 &&
3129 (screen->GetDisplayNearestWindow(window_).id() !=
3130 screen->GetDisplayNearestWindow(gained_focus).id());
3131 if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) {
3133 // On Windows, if we are switching to a non Aura Window on a different
3134 // screen we should not close the fullscreen window.
3135 if (!gained_focus) {
3137 ::GetCursorPos(&point);
3138 if (screen->GetDisplayNearestWindow(window_).id() !=
3139 screen->GetDisplayNearestPoint(gfx::Point(point)).id())
3143 in_shutdown_ = true;
3149 ////////////////////////////////////////////////////////////////////////////////
3150 // RenderWidgetHostViewAura, aura::WindowTreeHostObserver implementation:
3152 void RenderWidgetHostViewAura::OnHostMoved(const aura::WindowTreeHost* host,
3153 const gfx::Point& new_origin) {
3154 TRACE_EVENT1("ui", "RenderWidgetHostViewAura::OnHostMoved",
3155 "new_origin", new_origin.ToString());
3157 UpdateScreenInfo(window_);
3160 ////////////////////////////////////////////////////////////////////////////////
3161 // RenderWidgetHostViewAura, SoftwareFrameManagerClient implementation:
3163 void RenderWidgetHostViewAura::SoftwareFrameWasFreed(
3164 uint32 output_surface_id, unsigned frame_id) {
3165 ReleaseSoftwareFrame(output_surface_id, frame_id);
3168 void RenderWidgetHostViewAura::ReleaseReferencesToSoftwareFrame() {
3169 ui::Compositor* compositor = GetCompositor();
3171 AddOnCommitCallbackAndDisableLocks(base::Bind(
3172 &RenderWidgetHostViewAura::SendReclaimSoftwareFrames, AsWeakPtr()));
3174 UpdateExternalTexture();
3177 ////////////////////////////////////////////////////////////////////////////////
3178 // RenderWidgetHostViewAura, ui::CompositorObserver implementation:
3180 void RenderWidgetHostViewAura::OnCompositingDidCommit(
3181 ui::Compositor* compositor) {
3182 if (can_lock_compositor_ == NO_PENDING_COMMIT) {
3183 can_lock_compositor_ = YES;
3184 if (resize_lock_.get() && resize_lock_->GrabDeferredLock())
3185 can_lock_compositor_ = YES_DID_LOCK;
3187 RunOnCommitCallbacks();
3188 if (resize_lock_ && resize_lock_->expected_size() == current_frame_size_) {
3189 resize_lock_.reset();
3190 host_->WasResized();
3191 // We may have had a resize while we had the lock (e.g. if the lock expired,
3192 // or if the UI still gave us some resizes), so make sure we grab a new lock
3194 MaybeCreateResizeLock();
3198 void RenderWidgetHostViewAura::OnCompositingStarted(
3199 ui::Compositor* compositor, base::TimeTicks start_time) {
3200 last_draw_ended_ = start_time;
3203 void RenderWidgetHostViewAura::OnCompositingEnded(
3204 ui::Compositor* compositor) {
3207 void RenderWidgetHostViewAura::OnCompositingAborted(
3208 ui::Compositor* compositor) {
3211 void RenderWidgetHostViewAura::OnCompositingLockStateChanged(
3212 ui::Compositor* compositor) {
3213 // A compositor lock that is part of a resize lock timed out. We
3214 // should display a renderer frame.
3215 if (!compositor->IsLocked() && can_lock_compositor_ == YES_DID_LOCK) {
3216 can_lock_compositor_ = NO_PENDING_RENDERER_FRAME;
3220 void RenderWidgetHostViewAura::OnUpdateVSyncParameters(
3221 base::TimeTicks timebase,
3222 base::TimeDelta interval) {
3224 host_->UpdateVSyncParameters(timebase, interval);
3227 ////////////////////////////////////////////////////////////////////////////////
3228 // RenderWidgetHostViewAura, BrowserAccessibilityDelegate implementation:
3230 void RenderWidgetHostViewAura::SetAccessibilityFocus(int acc_obj_id) {
3234 host_->AccessibilitySetFocus(acc_obj_id);
3237 void RenderWidgetHostViewAura::AccessibilityDoDefaultAction(int acc_obj_id) {
3241 host_->AccessibilityDoDefaultAction(acc_obj_id);
3244 void RenderWidgetHostViewAura::AccessibilityScrollToMakeVisible(
3245 int acc_obj_id, gfx::Rect subfocus) {
3249 host_->AccessibilityScrollToMakeVisible(acc_obj_id, subfocus);
3252 void RenderWidgetHostViewAura::AccessibilityScrollToPoint(
3253 int acc_obj_id, gfx::Point point) {
3257 host_->AccessibilityScrollToPoint(acc_obj_id, point);
3260 void RenderWidgetHostViewAura::AccessibilitySetTextSelection(
3261 int acc_obj_id, int start_offset, int end_offset) {
3265 host_->AccessibilitySetTextSelection(
3266 acc_obj_id, start_offset, end_offset);
3269 gfx::Point RenderWidgetHostViewAura::GetLastTouchEventLocation() const {
3270 // Only needed for Win 8 non-aura.
3271 return gfx::Point();
3274 void RenderWidgetHostViewAura::FatalAccessibilityTreeError() {
3275 host_->FatalAccessibilityTreeError();
3276 SetBrowserAccessibilityManager(NULL);
3279 ////////////////////////////////////////////////////////////////////////////////
3280 // RenderWidgetHostViewAura, ImageTransportFactoryObserver implementation:
3282 void RenderWidgetHostViewAura::OnLostResources() {
3283 current_surface_ = NULL;
3284 UpdateExternalTexture();
3286 idle_frame_subscriber_textures_.clear();
3287 yuv_readback_pipeline_.reset();
3289 // Make sure all ImageTransportClients are deleted now that the context those
3290 // are using is becoming invalid. This sends pending ACKs and needs to happen
3291 // after calling UpdateExternalTexture() which syncs with the impl thread.
3292 RunOnCommitCallbacks();
3293 host_->ScheduleComposite();
3296 ////////////////////////////////////////////////////////////////////////////////
3297 // RenderWidgetHostViewAura, private:
3299 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
3300 if (touch_editing_client_)
3301 touch_editing_client_->OnViewDestroyed();
3303 ImageTransportFactory::GetInstance()->RemoveObserver(this);
3305 window_observer_.reset();
3306 if (window_->GetHost())
3307 window_->GetHost()->RemoveObserver(this);
3309 if (popup_parent_host_view_) {
3310 DCHECK(popup_parent_host_view_->popup_child_host_view_ == NULL ||
3311 popup_parent_host_view_->popup_child_host_view_ == this);
3312 popup_parent_host_view_->popup_child_host_view_ = NULL;
3314 if (popup_child_host_view_) {
3315 DCHECK(popup_child_host_view_->popup_parent_host_view_ == NULL ||
3316 popup_child_host_view_->popup_parent_host_view_ == this);
3317 popup_child_host_view_->popup_parent_host_view_ = NULL;
3319 event_filter_for_popup_exit_.reset();
3320 aura::client::SetTooltipText(window_, NULL);
3321 gfx::Screen::GetScreenFor(window_)->RemoveObserver(this);
3323 // This call is usually no-op since |this| object is already removed from the
3324 // Aura root window and we don't have a way to get an input method object
3325 // associated with the window, but just in case.
3326 DetachFromInputMethod();
3328 if (resource_collection_.get())
3329 resource_collection_->SetClient(NULL);
3331 // An OwnedMailbox should not refer to the GLHelper anymore once the RWHVA is
3332 // destroyed, as it may then outlive the GLHelper.
3333 for (std::set<OwnedMailbox*>::iterator it =
3334 active_frame_subscriber_textures_.begin();
3335 it != active_frame_subscriber_textures_.end();
3339 active_frame_subscriber_textures_.clear();
3342 legacy_render_widget_host_HWND_.reset(NULL);
3345 DCHECK(!vsync_manager_);
3348 void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
3349 const gfx::Point screen_point =
3350 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
3351 aura::Window* root_window = window_->GetRootWindow();
3355 gfx::Point root_window_point = screen_point;
3356 aura::client::ScreenPositionClient* screen_position_client =
3357 aura::client::GetScreenPositionClient(root_window);
3358 if (screen_position_client) {
3359 screen_position_client->ConvertPointFromScreen(
3360 root_window, &root_window_point);
3363 if (root_window->GetEventHandlerForPoint(root_window_point) != window_)
3366 gfx::NativeCursor cursor = current_cursor_.GetNativeCursor();
3367 // Do not show loading cursor when the cursor is currently hidden.
3368 if (is_loading_ && cursor != ui::kCursorNone)
3369 cursor = ui::kCursorPointer;
3371 aura::client::CursorClient* cursor_client =
3372 aura::client::GetCursorClient(root_window);
3373 if (cursor_client) {
3374 cursor_client->SetCursor(cursor);
3378 ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
3379 aura::Window* root_window = window_->GetRootWindow();
3382 return root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
3385 bool RenderWidgetHostViewAura::NeedsInputGrab() {
3386 return popup_type_ == blink::WebPopupTypeSelect;
3389 void RenderWidgetHostViewAura::FinishImeCompositionSession() {
3390 if (!has_composition_text_)
3393 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
3396 ImeCancelComposition();
3399 void RenderWidgetHostViewAura::ModifyEventMovementAndCoords(
3400 blink::WebMouseEvent* event) {
3401 // If the mouse has just entered, we must report zero movementX/Y. Hence we
3402 // reset any global_mouse_position set previously.
3403 if (event->type == blink::WebInputEvent::MouseEnter ||
3404 event->type == blink::WebInputEvent::MouseLeave)
3405 global_mouse_position_.SetPoint(event->globalX, event->globalY);
3407 // Movement is computed by taking the difference of the new cursor position
3408 // and the previous. Under mouse lock the cursor will be warped back to the
3409 // center so that we are not limited by clipping boundaries.
3410 // We do not measure movement as the delta from cursor to center because
3411 // we may receive more mouse movement events before our warp has taken
3413 event->movementX = event->globalX - global_mouse_position_.x();
3414 event->movementY = event->globalY - global_mouse_position_.y();
3416 global_mouse_position_.SetPoint(event->globalX, event->globalY);
3418 // Under mouse lock, coordinates of mouse are locked to what they were when
3419 // mouse lock was entered.
3420 if (mouse_locked_) {
3421 event->x = unlocked_mouse_position_.x();
3422 event->y = unlocked_mouse_position_.y();
3423 event->windowX = unlocked_mouse_position_.x();
3424 event->windowY = unlocked_mouse_position_.y();
3425 event->globalX = unlocked_global_mouse_position_.x();
3426 event->globalY = unlocked_global_mouse_position_.y();
3428 unlocked_mouse_position_.SetPoint(event->windowX, event->windowY);
3429 unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY);
3433 void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
3435 if (host_->is_hidden() ||
3436 (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) ||
3437 (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible))
3440 cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE;
3441 host_->SendCursorVisibilityState(is_visible);
3444 void RenderWidgetHostViewAura::SchedulePaintIfNotInClip(
3445 const gfx::Rect& rect,
3446 const gfx::Rect& clip) {
3447 if (!clip.IsEmpty()) {
3448 gfx::Rect to_paint = gfx::SubtractRects(rect, clip);
3449 if (!to_paint.IsEmpty())
3450 window_->SchedulePaintInRect(to_paint);
3452 window_->SchedulePaintInRect(rect);
3456 bool RenderWidgetHostViewAura::ShouldMoveToCenter() {
3457 gfx::Rect rect = window_->bounds();
3458 rect = ConvertRectToScreen(rect);
3459 int border_x = rect.width() * kMouseLockBorderPercentage / 100;
3460 int border_y = rect.height() * kMouseLockBorderPercentage / 100;
3462 return global_mouse_position_.x() < rect.x() + border_x ||
3463 global_mouse_position_.x() > rect.right() - border_x ||
3464 global_mouse_position_.y() < rect.y() + border_y ||
3465 global_mouse_position_.y() > rect.bottom() - border_y;
3468 void RenderWidgetHostViewAura::RunOnCommitCallbacks() {
3469 for (std::vector<base::Closure>::const_iterator
3470 it = on_compositing_did_commit_callbacks_.begin();
3471 it != on_compositing_did_commit_callbacks_.end(); ++it) {
3474 on_compositing_did_commit_callbacks_.clear();
3477 void RenderWidgetHostViewAura::AddOnCommitCallbackAndDisableLocks(
3478 const base::Closure& callback) {
3479 ui::Compositor* compositor = GetCompositor();
3482 if (!compositor->HasObserver(this))
3483 compositor->AddObserver(this);
3485 can_lock_compositor_ = NO_PENDING_COMMIT;
3486 on_compositing_did_commit_callbacks_.push_back(callback);
3489 void RenderWidgetHostViewAura::AddedToRootWindow() {
3490 window_->GetHost()->AddObserver(this);
3491 UpdateScreenInfo(window_);
3493 aura::client::CursorClient* cursor_client =
3494 aura::client::GetCursorClient(window_->GetRootWindow());
3495 if (cursor_client) {
3496 cursor_client->AddObserver(this);
3497 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
3499 if (current_surface_.get())
3500 UpdateExternalTexture();
3502 ui::InputMethod* input_method = GetInputMethod();
3504 input_method->SetFocusedTextInputClient(this);
3508 // The parent may have changed here. Ensure that the legacy window is
3509 // reparented accordingly.
3510 if (legacy_render_widget_host_HWND_)
3511 legacy_render_widget_host_HWND_->UpdateParent(
3512 reinterpret_cast<HWND>(GetNativeViewId()));
3515 ui::Compositor* compositor = GetCompositor();
3517 DCHECK(!vsync_manager_);
3518 vsync_manager_ = compositor->vsync_manager();
3519 vsync_manager_->AddObserver(this);
3523 void RenderWidgetHostViewAura::RemovingFromRootWindow() {
3524 aura::client::CursorClient* cursor_client =
3525 aura::client::GetCursorClient(window_->GetRootWindow());
3527 cursor_client->RemoveObserver(this);
3529 DetachFromInputMethod();
3531 window_->GetHost()->RemoveObserver(this);
3532 ui::Compositor* compositor = GetCompositor();
3533 if (current_surface_.get()) {
3534 // We can't get notification for commits after this point, which would
3535 // guarantee that the compositor isn't using an old texture any more, so
3536 // instead we force the layer to stop using any external resources which
3537 // synchronizes with the compositor thread, and makes it safe to run the
3539 window_->layer()->SetShowPaintedContent();
3541 RunOnCommitCallbacks();
3542 resize_lock_.reset();
3543 host_->WasResized();
3545 if (compositor && compositor->HasObserver(this))
3546 compositor->RemoveObserver(this);
3549 // Update the legacy window's parent temporarily to the desktop window. It
3550 // will eventually get reparented to the right root.
3551 if (legacy_render_widget_host_HWND_)
3552 legacy_render_widget_host_HWND_->UpdateParent(::GetDesktopWindow());
3555 if (vsync_manager_) {
3556 vsync_manager_->RemoveObserver(this);
3557 vsync_manager_ = NULL;
3561 ui::Compositor* RenderWidgetHostViewAura::GetCompositor() const {
3562 aura::WindowTreeHost* host = window_->GetHost();
3563 return host ? host->compositor() : NULL;
3566 void RenderWidgetHostViewAura::DetachFromInputMethod() {
3567 ui::InputMethod* input_method = GetInputMethod();
3568 if (input_method && input_method->GetTextInputClient() == this)
3569 input_method->SetFocusedTextInputClient(NULL);
3572 void RenderWidgetHostViewAura::LockResources() {
3573 DCHECK(frame_provider_);
3574 delegated_frame_evictor_->LockFrame();
3577 void RenderWidgetHostViewAura::UnlockResources() {
3578 DCHECK(frame_provider_);
3579 delegated_frame_evictor_->UnlockFrame();
3582 SkBitmap::Config RenderWidgetHostViewAura::PreferredReadbackFormat() {
3583 return SkBitmap::kARGB_8888_Config;
3586 ////////////////////////////////////////////////////////////////////////////////
3587 // RenderWidgetHostViewAura, ui::LayerOwnerDelegate implementation:
3589 void RenderWidgetHostViewAura::OnLayerRecreated(ui::Layer* old_layer,
3590 ui::Layer* new_layer) {
3591 float mailbox_scale_factor;
3592 cc::TextureMailbox old_mailbox =
3593 old_layer->GetTextureMailbox(&mailbox_scale_factor);
3594 scoped_refptr<ui::Texture> old_texture = old_layer->external_texture();
3595 // The new_layer is the one that will be used by our Window, so that's the one
3596 // that should keep our texture. old_layer will be returned to the
3597 // RecreateLayer caller, and should have a copy.
3598 if (old_texture.get()) {
3599 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
3600 GLHelper* gl_helper = factory->GetGLHelper();
3601 scoped_refptr<ui::Texture> new_texture;
3602 if (host_->is_accelerated_compositing_active() &&
3603 gl_helper && current_surface_.get()) {
3605 gl_helper->CopyTexture(current_surface_->PrepareTexture(),
3606 current_surface_->size());
3608 new_texture = factory->CreateOwnedTexture(
3609 current_surface_->size(),
3610 current_surface_->device_scale_factor(), texture_id);
3613 if (new_texture.get())
3614 old_layer->SetExternalTexture(new_texture.get());
3616 old_layer->SetShowPaintedContent();
3617 new_layer->SetExternalTexture(old_texture.get());
3618 } else if (old_mailbox.IsSharedMemory()) {
3619 base::SharedMemory* old_buffer = old_mailbox.shared_memory();
3620 const size_t size = old_mailbox.shared_memory_size_in_bytes();
3622 scoped_ptr<base::SharedMemory> new_buffer(new base::SharedMemory);
3623 new_buffer->CreateAndMapAnonymous(size);
3625 if (old_buffer->memory() && new_buffer->memory()) {
3626 memcpy(new_buffer->memory(), old_buffer->memory(), size);
3627 base::SharedMemory* new_buffer_raw_ptr = new_buffer.get();
3628 scoped_ptr<cc::SingleReleaseCallback> callback =
3629 cc::SingleReleaseCallback::Create(base::Bind(MailboxReleaseCallback,
3630 Passed(&new_buffer)));
3631 cc::TextureMailbox new_mailbox(new_buffer_raw_ptr,
3632 old_mailbox.shared_memory_size());
3633 new_layer->SetTextureMailbox(new_mailbox,
3635 mailbox_scale_factor);
3637 } else if (frame_provider_.get()) {
3638 new_layer->SetShowDelegatedContent(frame_provider_.get(),
3639 current_frame_size_);
3643 ////////////////////////////////////////////////////////////////////////////////
3644 // RenderWidgetHostView, public:
3647 RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
3648 RenderWidgetHost* widget) {
3649 return new RenderWidgetHostViewAura(widget);
3653 void RenderWidgetHostViewPort::GetDefaultScreenInfo(WebScreenInfo* results) {
3654 GetScreenInfoForWindow(results, NULL);
3657 } // namespace content