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/gpu/compositor_util.h"
26 #include "content/browser/renderer_host/backing_store_aura.h"
27 #include "content/browser/renderer_host/compositor_resize_lock_aura.h"
28 #include "content/browser/renderer_host/dip_util.h"
29 #include "content/browser/renderer_host/input/synthetic_gesture_target_aura.h"
30 #include "content/browser/renderer_host/overscroll_controller.h"
31 #include "content/browser/renderer_host/render_view_host_delegate.h"
32 #include "content/browser/renderer_host/render_widget_host_impl.h"
33 #include "content/browser/renderer_host/ui_events_helper.h"
34 #include "content/browser/renderer_host/web_input_event_aura.h"
35 #include "content/common/gpu/client/gl_helper.h"
36 #include "content/common/gpu/gpu_messages.h"
37 #include "content/common/view_messages.h"
38 #include "content/port/browser/render_widget_host_view_frame_subscriber.h"
39 #include "content/port/browser/render_widget_host_view_port.h"
40 #include "content/public/browser/content_browser_client.h"
41 #include "content/public/browser/render_process_host.h"
42 #include "content/public/browser/render_view_host.h"
43 #include "content/public/browser/user_metrics.h"
44 #include "content/public/common/content_switches.h"
45 #include "media/base/video_util.h"
46 #include "skia/ext/image_operations.h"
47 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
48 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
49 #include "third_party/WebKit/public/web/WebInputEvent.h"
50 #include "ui/aura/client/activation_client.h"
51 #include "ui/aura/client/aura_constants.h"
52 #include "ui/aura/client/cursor_client.h"
53 #include "ui/aura/client/cursor_client_observer.h"
54 #include "ui/aura/client/focus_client.h"
55 #include "ui/aura/client/scoped_tooltip_disabler.h"
56 #include "ui/aura/client/screen_position_client.h"
57 #include "ui/aura/client/tooltip_client.h"
58 #include "ui/aura/client/transient_window_client.h"
59 #include "ui/aura/client/window_tree_client.h"
60 #include "ui/aura/env.h"
61 #include "ui/aura/root_window.h"
62 #include "ui/aura/window.h"
63 #include "ui/aura/window_observer.h"
64 #include "ui/aura/window_tracker.h"
65 #include "ui/base/clipboard/scoped_clipboard_writer.h"
66 #include "ui/base/hit_test.h"
67 #include "ui/base/ime/input_method.h"
68 #include "ui/base/ui_base_types.h"
69 #include "ui/compositor/compositor_vsync_manager.h"
70 #include "ui/compositor/layer.h"
71 #include "ui/events/event.h"
72 #include "ui/events/event_utils.h"
73 #include "ui/events/gestures/gesture_recognizer.h"
74 #include "ui/gfx/canvas.h"
75 #include "ui/gfx/display.h"
76 #include "ui/gfx/rect_conversions.h"
77 #include "ui/gfx/screen.h"
78 #include "ui/gfx/size_conversions.h"
79 #include "ui/gfx/skia_util.h"
80 #include "ui/wm/public/window_types.h"
83 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
84 #include "content/browser/accessibility/browser_accessibility_win.h"
85 #include "content/browser/renderer_host/legacy_render_widget_host_win.h"
86 #include "content/common/plugin_constants_win.h"
87 #include "ui/base/win/hidden_window.h"
88 #include "ui/gfx/gdi_util.h"
89 #include "ui/gfx/win/dpi.h"
92 using gfx::RectToSkIRect;
93 using gfx::SkIRectToRect;
95 using blink::WebScreenInfo;
96 using blink::WebTouchEvent;
102 void MailboxReleaseCallback(scoped_ptr<base::SharedMemory> shared_memory,
104 bool lost_resource) {
105 // NOTE: shared_memory will get released when we go out of scope.
108 // In mouse lock mode, we need to prevent the (invisible) cursor from hitting
109 // the border of the view, in order to get valid movement information. However,
110 // forcing the cursor back to the center of the view after each mouse move
111 // doesn't work well. It reduces the frequency of useful mouse move messages
112 // significantly. Therefore, we move the cursor to the center of the view only
113 // if it approaches the border. |kMouseLockBorderPercentage| specifies the width
114 // of the border area, in percentage of the corresponding dimension.
115 const int kMouseLockBorderPercentage = 15;
117 // When accelerated compositing is enabled and a widget resize is pending,
118 // we delay further resizes of the UI. The following constant is the maximum
119 // length of time that we should delay further UI resizes while waiting for a
120 // resized frame from a renderer.
121 const int kResizeLockTimeoutMs = 67;
124 // Used to associate a plugin HWND with its RenderWidgetHostViewAura instance.
125 const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner";
127 BOOL CALLBACK WindowDestroyingCallback(HWND window, LPARAM param) {
128 RenderWidgetHostViewAura* widget =
129 reinterpret_cast<RenderWidgetHostViewAura*>(param);
130 if (GetProp(window, kWidgetOwnerProperty) == widget) {
131 // Properties set on HWNDs must be removed to avoid leaks.
132 RemoveProp(window, kWidgetOwnerProperty);
133 RenderWidgetHostViewBase::DetachPluginWindowsCallback(window);
138 BOOL CALLBACK HideWindowsCallback(HWND window, LPARAM param) {
139 RenderWidgetHostViewAura* widget =
140 reinterpret_cast<RenderWidgetHostViewAura*>(param);
141 if (GetProp(window, kWidgetOwnerProperty) == widget)
142 SetParent(window, ui::GetHiddenWindow());
146 BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) {
147 RenderWidgetHostViewAura* widget =
148 reinterpret_cast<RenderWidgetHostViewAura*>(param);
150 if (GetProp(window, kWidgetOwnerProperty) == widget &&
151 widget->GetNativeView()->GetDispatcher()) {
152 HWND parent = widget->GetNativeView()->GetDispatcher()->host()->
153 GetAcceleratedWidget();
154 SetParent(window, parent);
159 struct CutoutRectsParams {
160 RenderWidgetHostViewAura* widget;
161 std::vector<gfx::Rect> cutout_rects;
162 std::map<HWND, WebPluginGeometry>* geometry;
165 // Used to update the region for the windowed plugin to draw in. We start with
166 // the clip rect from the renderer, then remove the cutout rects from the
167 // renderer, and then remove the transient windows from the root window and the
168 // constrained windows from the parent window.
169 BOOL CALLBACK SetCutoutRectsCallback(HWND window, LPARAM param) {
170 CutoutRectsParams* params = reinterpret_cast<CutoutRectsParams*>(param);
172 if (GetProp(window, kWidgetOwnerProperty) == params->widget) {
173 // First calculate the offset of this plugin from the root window, since
174 // the cutouts are relative to the root window.
175 HWND parent = params->widget->GetNativeView()->GetDispatcher()->
176 host()->GetAcceleratedWidget();
178 offset.x = offset.y = 0;
179 MapWindowPoints(window, parent, &offset, 1);
181 // Now get the cached clip rect and cutouts for this plugin window that came
182 // from the renderer.
183 std::map<HWND, WebPluginGeometry>::iterator i = params->geometry->begin();
184 while (i != params->geometry->end() &&
185 i->second.window != window &&
186 GetParent(i->second.window) != window) {
190 if (i == params->geometry->end()) {
195 HRGN hrgn = CreateRectRgn(i->second.clip_rect.x(),
196 i->second.clip_rect.y(),
197 i->second.clip_rect.right(),
198 i->second.clip_rect.bottom());
199 // We start with the cutout rects that came from the renderer, then add the
200 // ones that came from transient and constrained windows.
201 std::vector<gfx::Rect> cutout_rects = i->second.cutout_rects;
202 for (size_t i = 0; i < params->cutout_rects.size(); ++i) {
203 gfx::Rect offset_cutout = params->cutout_rects[i];
204 offset_cutout.Offset(-offset.x, -offset.y);
205 cutout_rects.push_back(offset_cutout);
207 gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects);
208 // If we don't have any cutout rects then no point in messing with the
210 if (cutout_rects.size())
211 SetWindowRgn(window, hrgn, TRUE);
216 // A callback function for EnumThreadWindows to enumerate and dismiss
217 // any owned popup windows.
218 BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
219 const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);
221 if (::IsWindowVisible(window)) {
222 const HWND owner = ::GetWindow(window, GW_OWNER);
223 if (toplevel_hwnd == owner) {
224 ::PostMessage(window, WM_CANCELMODE, 0, 0);
232 void UpdateWebTouchEventAfterDispatch(blink::WebTouchEvent* event,
233 blink::WebTouchPoint* point) {
234 if (point->state != blink::WebTouchPoint::StateReleased &&
235 point->state != blink::WebTouchPoint::StateCancelled)
237 --event->touchesLength;
238 for (unsigned i = point - event->touches;
239 i < event->touchesLength;
241 event->touches[i] = event->touches[i + 1];
245 bool CanRendererHandleEvent(const ui::MouseEvent* event) {
246 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
250 // Renderer cannot handle WM_XBUTTON or NC events.
251 switch (event->native_event().message) {
254 case WM_XBUTTONDBLCLK:
255 case WM_NCMOUSELEAVE:
257 case WM_NCLBUTTONDOWN:
259 case WM_NCLBUTTONDBLCLK:
260 case WM_NCRBUTTONDOWN:
262 case WM_NCRBUTTONDBLCLK:
263 case WM_NCMBUTTONDOWN:
265 case WM_NCMBUTTONDBLCLK:
266 case WM_NCXBUTTONDOWN:
268 case WM_NCXBUTTONDBLCLK:
277 // We don't mark these as handled so that they're sent back to the
278 // DefWindowProc so it can generate WM_APPCOMMAND as necessary.
279 bool IsXButtonUpEvent(const ui::MouseEvent* event) {
281 switch (event->native_event().message) {
290 void GetScreenInfoForWindow(WebScreenInfo* results, aura::Window* window) {
291 const gfx::Display display = window ?
292 gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window) :
293 gfx::Screen::GetScreenFor(window)->GetPrimaryDisplay();
294 results->rect = display.bounds();
295 results->availableRect = display.work_area();
296 // TODO(derat|oshima): Don't hardcode this. Get this from display object.
298 results->depthPerComponent = 8;
299 results->deviceScaleFactor = display.device_scale_factor();
302 bool PointerEventActivates(const ui::Event& event) {
303 if (event.type() == ui::ET_MOUSE_PRESSED)
306 if (event.type() == ui::ET_GESTURE_BEGIN) {
307 const ui::GestureEvent& gesture =
308 static_cast<const ui::GestureEvent&>(event);
309 return gesture.details().touch_points() == 1;
315 // Swap ack for the renderer when kCompositeToMailbox is enabled.
316 void SendCompositorFrameAck(
318 uint32 output_surface_id,
319 int renderer_host_id,
320 const gpu::Mailbox& received_mailbox,
321 const gfx::Size& received_size,
323 const scoped_refptr<ui::Texture>& texture_to_produce) {
324 cc::CompositorFrameAck ack;
325 ack.gl_frame_data.reset(new cc::GLFrameData());
326 DCHECK(!texture_to_produce.get() || !skip_frame);
327 if (texture_to_produce.get()) {
328 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
329 ack.gl_frame_data->mailbox = texture_to_produce->Produce();
330 ack.gl_frame_data->size = texture_to_produce->size();
331 ack.gl_frame_data->sync_point =
332 gl_helper ? gl_helper->InsertSyncPoint() : 0;
333 } else if (skip_frame) {
334 // Skip the frame, i.e. tell the producer to reuse the same buffer that
336 ack.gl_frame_data->size = received_size;
337 ack.gl_frame_data->mailbox = received_mailbox;
340 RenderWidgetHostImpl::SendSwapCompositorFrameAck(
341 route_id, output_surface_id, renderer_host_id, ack);
344 void AcknowledgeBufferForGpu(
347 const gpu::Mailbox& received_mailbox,
349 const scoped_refptr<ui::Texture>& texture_to_produce) {
350 AcceleratedSurfaceMsg_BufferPresented_Params ack;
351 uint32 sync_point = 0;
352 DCHECK(!texture_to_produce.get() || !skip_frame);
353 if (texture_to_produce.get()) {
354 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
355 ack.mailbox = texture_to_produce->Produce();
356 sync_point = gl_helper ? gl_helper->InsertSyncPoint() : 0;
357 } else if (skip_frame) {
358 ack.mailbox = received_mailbox;
362 ack.sync_point = sync_point;
363 RenderWidgetHostImpl::AcknowledgeBufferPresent(
364 route_id, gpu_host_id, ack);
369 // We need to watch for mouse events outside a Web Popup or its parent
370 // and dismiss the popup for certain events.
371 class RenderWidgetHostViewAura::EventFilterForPopupExit
372 : public ui::EventHandler {
374 explicit EventFilterForPopupExit(RenderWidgetHostViewAura* rwhva)
377 aura::Env::GetInstance()->AddPreTargetHandler(this);
380 virtual ~EventFilterForPopupExit() {
381 aura::Env::GetInstance()->RemovePreTargetHandler(this);
384 // Overridden from ui::EventHandler
385 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
386 rwhva_->ApplyEventFilterForPopupExit(event);
389 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
390 rwhva_->ApplyEventFilterForPopupExit(event);
394 RenderWidgetHostViewAura* rwhva_;
396 DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit);
399 void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
400 ui::LocatedEvent* event) {
401 if (in_shutdown_ || is_fullscreen_ || !event->target())
404 if (event->type() != ui::ET_MOUSE_PRESSED &&
405 event->type() != ui::ET_TOUCH_PRESSED) {
409 aura::Window* target = static_cast<aura::Window*>(event->target());
410 if (target != window_ &&
411 (!popup_parent_host_view_ ||
412 target != popup_parent_host_view_->window_)) {
413 // Note: popup_parent_host_view_ may be NULL when there are multiple
414 // popup children per view. See: RenderWidgetHostViewAura::InitAsPopup().
420 // We have to implement the WindowObserver interface on a separate object
421 // because clang doesn't like implementing multiple interfaces that have
422 // methods with the same name. This object is owned by the
423 // RenderWidgetHostViewAura.
424 class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver {
426 explicit WindowObserver(RenderWidgetHostViewAura* view)
428 view_->window_->AddObserver(this);
431 virtual ~WindowObserver() {
432 view_->window_->RemoveObserver(this);
435 // Overridden from aura::WindowObserver:
436 virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
437 if (window == view_->window_)
438 view_->AddedToRootWindow();
441 virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE {
442 if (window == view_->window_)
443 view_->RemovingFromRootWindow();
447 RenderWidgetHostViewAura* view_;
449 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
452 ////////////////////////////////////////////////////////////////////////////////
453 // RenderWidgetHostViewAura, public:
455 RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
456 : host_(RenderWidgetHostImpl::From(host)),
457 window_(new aura::Window(this)),
459 in_bounds_changed_(false),
460 is_fullscreen_(false),
461 popup_parent_host_view_(NULL),
462 popup_child_host_view_(NULL),
464 text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
465 text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
466 can_compose_inline_(true),
467 has_composition_text_(false),
468 accept_return_character_(false),
469 last_output_surface_id_(0),
470 pending_delegated_ack_count_(0),
471 skipped_frames_(false),
472 last_swapped_surface_scale_factor_(1.f),
474 synthetic_move_sent_(false),
475 accelerated_compositing_state_changed_(false),
476 can_lock_compositor_(YES),
477 cursor_visibility_state_in_renderer_(UNKNOWN),
478 touch_editing_client_(NULL),
479 delegated_frame_evictor_(new DelegatedFrameEvictor(this)),
480 weak_ptr_factory_(this) {
481 host_->SetView(this);
482 window_observer_.reset(new WindowObserver(this));
483 aura::client::SetTooltipText(window_, &tooltip_);
484 aura::client::SetActivationDelegate(window_, this);
485 aura::client::SetActivationChangeObserver(window_, this);
486 aura::client::SetFocusChangeObserver(window_, this);
487 gfx::Screen::GetScreenFor(window_)->AddObserver(this);
488 software_frame_manager_.reset(new SoftwareFrameManager(
489 weak_ptr_factory_.GetWeakPtr()));
490 ImageTransportFactory::GetInstance()->AddObserver(this);
493 ////////////////////////////////////////////////////////////////////////////////
494 // RenderWidgetHostViewAura, RenderWidgetHostView implementation:
496 bool RenderWidgetHostViewAura::OnMessageReceived(
497 const IPC::Message& message) {
499 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAura, message)
500 // TODO(kevers): Move to RenderWidgetHostViewImpl and consolidate IPC
501 // messages for TextInput<State|Type>Changed. Corresponding code in
502 // RenderWidgetHostViewAndroid should also be moved at the same time.
503 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
504 OnTextInputStateChanged)
505 IPC_MESSAGE_UNHANDLED(handled = false)
506 IPC_END_MESSAGE_MAP()
510 void RenderWidgetHostViewAura::InitAsChild(
511 gfx::NativeView parent_view) {
512 window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
513 window_->Init(aura::WINDOW_LAYER_TEXTURED);
514 window_->SetName("RenderWidgetHostViewAura");
517 void RenderWidgetHostViewAura::InitAsPopup(
518 RenderWidgetHostView* parent_host_view,
519 const gfx::Rect& bounds_in_screen) {
520 popup_parent_host_view_ =
521 static_cast<RenderWidgetHostViewAura*>(parent_host_view);
523 // TransientWindowClient may be NULL during tests.
524 aura::client::TransientWindowClient* transient_window_client =
525 aura::client::GetTransientWindowClient();
526 RenderWidgetHostViewAura* old_child =
527 popup_parent_host_view_->popup_child_host_view_;
529 // TODO(jhorwich): Allow multiple popup_child_host_view_ per view, or
530 // similar mechanism to ensure a second popup doesn't cause the first one
531 // to never get a chance to filter events. See crbug.com/160589.
532 DCHECK(old_child->popup_parent_host_view_ == popup_parent_host_view_);
533 if (transient_window_client) {
534 transient_window_client->RemoveTransientChild(
535 popup_parent_host_view_->window_, old_child->window_);
537 old_child->popup_parent_host_view_ = NULL;
539 popup_parent_host_view_->popup_child_host_view_ = this;
540 window_->SetType(ui::wm::WINDOW_TYPE_MENU);
541 window_->Init(aura::WINDOW_LAYER_TEXTURED);
542 window_->SetName("RenderWidgetHostViewAura");
544 aura::Window* root = popup_parent_host_view_->window_->GetRootWindow();
545 aura::client::ParentWindowWithContext(window_, root, bounds_in_screen);
546 // Setting the transient child allows for the popup to get mouse events when
547 // in a system modal dialog.
548 // This fixes crbug.com/328593.
549 if (transient_window_client) {
550 transient_window_client->AddTransientChild(
551 popup_parent_host_view_->window_, window_);
554 SetBounds(bounds_in_screen);
556 #if !defined(OS_WIN) && !defined(OS_CHROMEOS)
557 if (NeedsInputGrab())
558 window_->SetCapture();
561 event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
564 void RenderWidgetHostViewAura::InitAsFullscreen(
565 RenderWidgetHostView* reference_host_view) {
566 is_fullscreen_ = true;
567 window_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
568 window_->Init(aura::WINDOW_LAYER_TEXTURED);
569 window_->SetName("RenderWidgetHostViewAura");
570 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
572 aura::Window* parent = NULL;
574 if (reference_host_view) {
575 aura::Window* reference_window =
576 static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_;
577 if (reference_window) {
578 host_tracker_.reset(new aura::WindowTracker);
579 host_tracker_->Add(reference_window);
581 gfx::Display display = gfx::Screen::GetScreenFor(window_)->
582 GetDisplayNearestWindow(reference_window);
583 parent = reference_window->GetRootWindow();
584 bounds = display.bounds();
586 aura::client::ParentWindowWithContext(window_, parent, bounds);
591 RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
595 void RenderWidgetHostViewAura::WasShown() {
597 if (!host_->is_hidden())
600 software_frame_manager_->SetVisibility(true);
601 delegated_frame_evictor_->SetVisible(true);
603 aura::Window* root = window_->GetRootWindow();
605 aura::client::CursorClient* cursor_client =
606 aura::client::GetCursorClient(root);
608 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
611 if (!current_surface_.get() && host_->is_accelerated_compositing_active() &&
612 !released_front_lock_.get()) {
613 ui::Compositor* compositor = GetCompositor();
615 released_front_lock_ = compositor->GetCompositorLock();
619 if (legacy_render_widget_host_HWND_) {
620 // Reparent the legacy Chrome_RenderWidgetHostHWND window to the parent
621 // window before reparenting any plugins. This ensures that the plugin
622 // windows stay on top of the child Zorder in the parent and receive
623 // mouse events, etc.
624 legacy_render_widget_host_HWND_->UpdateParent(
625 GetNativeView()->GetDispatcher()->host()->GetAcceleratedWidget());
626 legacy_render_widget_host_HWND_->SetBounds(
627 window_->GetBoundsInRootWindow());
629 LPARAM lparam = reinterpret_cast<LPARAM>(this);
630 EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
634 void RenderWidgetHostViewAura::WasHidden() {
635 if (!host_ || host_->is_hidden())
638 software_frame_manager_->SetVisibility(false);
639 delegated_frame_evictor_->SetVisible(false);
640 released_front_lock_ = NULL;
643 constrained_rects_.clear();
644 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
646 HWND parent = dispatcher->host()->GetAcceleratedWidget();
647 LPARAM lparam = reinterpret_cast<LPARAM>(this);
648 EnumChildWindows(parent, HideWindowsCallback, lparam);
649 // We reparent the legacy Chrome_RenderWidgetHostHWND window to the global
650 // hidden window on the same lines as Windowed plugin windows.
651 if (legacy_render_widget_host_HWND_)
652 legacy_render_widget_host_HWND_->UpdateParent(ui::GetHiddenWindow());
657 void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) {
658 // For a SetSize operation, we don't care what coordinate system the origin
659 // of the window is in, it's only important to make sure that the origin
660 // remains constant after the operation.
661 InternalSetBounds(gfx::Rect(window_->bounds().origin(), size));
664 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
665 gfx::Point relative_origin(rect.origin());
667 // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but
668 // Window::SetBounds() takes parent coordinates, so do the conversion here.
669 aura::Window* root = window_->GetRootWindow();
671 aura::client::ScreenPositionClient* screen_position_client =
672 aura::client::GetScreenPositionClient(root);
673 if (screen_position_client) {
674 screen_position_client->ConvertPointFromScreen(
675 window_->parent(), &relative_origin);
679 InternalSetBounds(gfx::Rect(relative_origin, rect.size()));
682 void RenderWidgetHostViewAura::MaybeCreateResizeLock() {
683 if (!ShouldCreateResizeLock())
685 DCHECK(window_->GetDispatcher());
686 DCHECK(window_->GetDispatcher()->host()->compositor());
688 // Listen to changes in the compositor lock state.
689 ui::Compositor* compositor = window_->GetDispatcher()->host()->compositor();
690 if (!compositor->HasObserver(this))
691 compositor->AddObserver(this);
693 bool defer_compositor_lock =
694 can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
695 can_lock_compositor_ == NO_PENDING_COMMIT;
697 if (can_lock_compositor_ == YES)
698 can_lock_compositor_ = YES_DID_LOCK;
700 resize_lock_ = CreateResizeLock(defer_compositor_lock);
703 bool RenderWidgetHostViewAura::ShouldCreateResizeLock() {
704 // On Windows while resizing, the the resize locks makes us mis-paint a white
705 // vertical strip (including the non-client area) if the content composition
706 // is lagging the UI composition. So here we disable the throttling so that
707 // the UI bits can draw ahead of the content thereby reducing the amount of
708 // whiteout. Because this causes the content to be drawn at wrong sizes while
709 // resizing we compensate by blocking the UI thread in Compositor::Draw() by
710 // issuing a FinishAllRendering() if we are resizing.
718 if (host_->should_auto_resize())
720 if (!host_->is_accelerated_compositing_active())
723 gfx::Size desired_size = window_->bounds().size();
724 if (desired_size == current_frame_size_)
727 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
731 ui::Compositor* compositor = dispatcher->host()->compositor();
738 scoped_ptr<ResizeLock> RenderWidgetHostViewAura::CreateResizeLock(
739 bool defer_compositor_lock) {
740 gfx::Size desired_size = window_->bounds().size();
741 return scoped_ptr<ResizeLock>(new CompositorResizeLock(
742 window_->GetDispatcher(),
744 defer_compositor_lock,
745 base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs)));
748 void RenderWidgetHostViewAura::RequestCopyOfOutput(
749 scoped_ptr<cc::CopyOutputRequest> request) {
750 window_->layer()->RequestCopyOfOutput(request.Pass());
753 gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
757 gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const {
759 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
761 return reinterpret_cast<gfx::NativeViewId>(
762 dispatcher->host()->GetAcceleratedWidget());
764 return static_cast<gfx::NativeViewId>(NULL);
767 gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
769 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
771 return static_cast<gfx::NativeViewAccessible>(NULL);
772 HWND hwnd = dispatcher->host()->GetAcceleratedWidget();
774 CreateBrowserAccessibilityManagerIfNeeded();
775 BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
777 return manager->GetRoot()->ToBrowserAccessibilityWin();
781 return static_cast<gfx::NativeViewAccessible>(NULL);
784 void RenderWidgetHostViewAura::SetKeyboardFocus() {
787 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
789 ::SetFocus(dispatcher->host()->GetAcceleratedWidget());
794 void RenderWidgetHostViewAura::MovePluginWindows(
795 const gfx::Vector2d& scroll_offset,
796 const std::vector<WebPluginGeometry>& plugin_window_moves) {
798 // We need to clip the rectangle to the tab's viewport, otherwise we will draw
799 // over the browser UI.
800 if (!window_->GetRootWindow()) {
801 DCHECK(plugin_window_moves.empty());
804 HWND parent = window_->GetDispatcher()->host()->GetAcceleratedWidget();
805 gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
806 std::vector<WebPluginGeometry> moves = plugin_window_moves;
808 gfx::Rect view_port(scroll_offset.x(), scroll_offset.y(), view_bounds.width(),
809 view_bounds.height());
811 for (size_t i = 0; i < moves.size(); ++i) {
812 gfx::Rect clip(moves[i].clip_rect);
813 gfx::Vector2d view_port_offset(
814 moves[i].window_rect.OffsetFromOrigin() + scroll_offset);
815 clip.Offset(view_port_offset);
816 clip.Intersect(view_port);
817 clip.Offset(-view_port_offset);
818 moves[i].clip_rect = clip;
820 moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin());
822 plugin_window_moves_[moves[i].window] = moves[i];
824 // constrained_rects_ are relative to the root window. We want to convert
825 // them to be relative to the plugin window.
826 for (size_t j = 0; j < constrained_rects_.size(); ++j) {
827 gfx::Rect offset_cutout = constrained_rects_[j];
828 offset_cutout -= moves[i].window_rect.OffsetFromOrigin();
829 moves[i].cutout_rects.push_back(offset_cutout);
833 MovePluginWindowsHelper(parent, moves);
835 // Make sure each plugin window (or its wrapper if it exists) has a pointer to
837 for (size_t i = 0; i < moves.size(); ++i) {
838 HWND window = moves[i].window;
839 if (GetParent(window) != parent) {
840 window = GetParent(window);
842 if (!GetProp(window, kWidgetOwnerProperty))
843 SetProp(window, kWidgetOwnerProperty, this);
845 #endif // defined(OS_WIN)
848 void RenderWidgetHostViewAura::Focus() {
849 // Make sure we have a FocusClient before attempting to Focus(). In some
850 // situations we may not yet be in a valid Window hierarchy (such as reloading
851 // after out of memory discarded the tab).
852 aura::client::FocusClient* client = aura::client::GetFocusClient(window_);
857 void RenderWidgetHostViewAura::Blur() {
861 bool RenderWidgetHostViewAura::HasFocus() const {
862 return window_->HasFocus();
865 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
866 return CanCopyToBitmap() || !!host_->GetBackingStore(false);
869 void RenderWidgetHostViewAura::Show() {
873 if (legacy_render_widget_host_HWND_)
874 legacy_render_widget_host_HWND_->Show();
878 void RenderWidgetHostViewAura::Hide() {
882 if (legacy_render_widget_host_HWND_)
883 legacy_render_widget_host_HWND_->Hide();
887 bool RenderWidgetHostViewAura::IsShowing() {
888 return window_->IsVisible();
891 gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
892 // This is the size that we want the renderer to produce. While we're waiting
893 // for the correct frame (i.e. during a resize), don't change the size so that
894 // we don't pipeline more resizes than we can handle.
895 gfx::Rect bounds(window_->GetBoundsInScreen());
896 if (resize_lock_.get())
897 return gfx::Rect(bounds.origin(), resize_lock_->expected_size());
902 void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) {
903 RenderWidgetHostViewBase::SetBackground(background);
904 host_->SetBackground(background);
905 window_->layer()->SetFillsBoundsOpaquely(background.isOpaque());
908 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
909 current_cursor_ = cursor;
910 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
911 GetDisplayNearestWindow(window_);
912 current_cursor_.SetDisplayInfo(display);
913 UpdateCursorIfOverSelf();
916 void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
917 is_loading_ = is_loading;
918 UpdateCursorIfOverSelf();
921 void RenderWidgetHostViewAura::TextInputTypeChanged(
922 ui::TextInputType type,
923 ui::TextInputMode input_mode,
924 bool can_compose_inline) {
925 if (text_input_type_ != type ||
926 text_input_mode_ != input_mode ||
927 can_compose_inline_ != can_compose_inline) {
928 text_input_type_ = type;
929 text_input_mode_ = input_mode;
930 can_compose_inline_ = can_compose_inline;
931 if (GetInputMethod())
932 GetInputMethod()->OnTextInputTypeChanged(this);
933 if (touch_editing_client_)
934 touch_editing_client_->OnTextInputTypeChanged(text_input_type_);
938 void RenderWidgetHostViewAura::OnTextInputStateChanged(
939 const ViewHostMsg_TextInputState_Params& params) {
940 if (params.show_ime_if_needed && params.type != ui::TEXT_INPUT_TYPE_NONE) {
941 if (GetInputMethod())
942 GetInputMethod()->ShowImeIfNeeded();
946 void RenderWidgetHostViewAura::ImeCancelComposition() {
947 if (GetInputMethod())
948 GetInputMethod()->CancelComposition(this);
949 has_composition_text_ = false;
952 void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
953 const gfx::Range& range,
954 const std::vector<gfx::Rect>& character_bounds) {
955 composition_character_bounds_ = character_bounds;
958 void RenderWidgetHostViewAura::DidUpdateBackingStore(
959 const gfx::Rect& scroll_rect,
960 const gfx::Vector2d& scroll_delta,
961 const std::vector<gfx::Rect>& copy_rects,
962 const std::vector<ui::LatencyInfo>& latency_info) {
963 if (accelerated_compositing_state_changed_)
964 UpdateExternalTexture();
966 for (size_t i = 0; i < latency_info.size(); i++)
967 software_latency_info_.push_back(latency_info[i]);
969 // Use the state of the RenderWidgetHost and not the window as the two may
970 // differ. In particular if the window is hidden but the renderer isn't and we
971 // ignore the update and the window is made visible again the layer isn't
972 // marked as dirty and we show the wrong thing.
973 // We do this after UpdateExternalTexture() so that when we become visible
974 // we're not drawing a stale texture.
975 if (host_->is_hidden())
981 if (paint_canvas_->sk_canvas()->getClipBounds(&sk_clip_rect))
982 clip_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(sk_clip_rect));
985 if (!scroll_rect.IsEmpty())
986 SchedulePaintIfNotInClip(scroll_rect, clip_rect);
989 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
991 for (size_t i = 0; i < copy_rects.size(); ++i) {
992 gfx::Rect rect = gfx::SubtractRects(copy_rects[i], scroll_rect);
996 SchedulePaintIfNotInClip(rect, clip_rect);
1000 // Send the invalid rect in screen coordinates.
1001 gfx::Rect screen_rect = GetViewBounds();
1002 gfx::Rect invalid_screen_rect(rect);
1003 invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y());
1004 HWND hwnd = dispatcher->host()->GetAcceleratedWidget();
1005 PaintPluginWindowsHelper(hwnd, invalid_screen_rect);
1007 #endif // defined(OS_WIN)
1011 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
1013 UpdateCursorIfOverSelf();
1017 void RenderWidgetHostViewAura::Destroy() {
1018 // Beware, this function is not called on all destruction paths. It will
1019 // implicitly end up calling ~RenderWidgetHostViewAura though, so all
1020 // destruction/cleanup code should happen there, not here.
1021 in_shutdown_ = true;
1025 void RenderWidgetHostViewAura::SetTooltipText(
1026 const base::string16& tooltip_text) {
1027 tooltip_ = tooltip_text;
1028 aura::Window* root_window = window_->GetRootWindow();
1029 aura::client::TooltipClient* tooltip_client =
1030 aura::client::GetTooltipClient(root_window);
1031 if (tooltip_client) {
1032 tooltip_client->UpdateTooltip(window_);
1033 // Content tooltips should be visible indefinitely.
1034 tooltip_client->SetTooltipShownTimeout(window_, 0);
1038 void RenderWidgetHostViewAura::SelectionChanged(const base::string16& text,
1040 const gfx::Range& range) {
1041 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
1043 #if defined(USE_X11) && !defined(OS_CHROMEOS)
1044 if (text.empty() || range.is_empty())
1047 // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard.
1048 ui::ScopedClipboardWriter clipboard_writer(
1049 ui::Clipboard::GetForCurrentThread(),
1050 ui::CLIPBOARD_TYPE_SELECTION);
1051 clipboard_writer.WriteText(text);
1052 #endif // defined(USE_X11) && !defined(OS_CHROMEOS)
1055 void RenderWidgetHostViewAura::SelectionBoundsChanged(
1056 const ViewHostMsg_SelectionBounds_Params& params) {
1057 if (selection_anchor_rect_ == params.anchor_rect &&
1058 selection_focus_rect_ == params.focus_rect)
1061 selection_anchor_rect_ = params.anchor_rect;
1062 selection_focus_rect_ = params.focus_rect;
1064 if (GetInputMethod())
1065 GetInputMethod()->OnCaretBoundsChanged(this);
1067 if (touch_editing_client_) {
1068 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
1069 selection_focus_rect_);
1073 void RenderWidgetHostViewAura::ScrollOffsetChanged() {
1074 aura::Window* root = window_->GetRootWindow();
1077 aura::client::CursorClient* cursor_client =
1078 aura::client::GetCursorClient(root);
1079 if (cursor_client && !cursor_client->IsCursorVisible())
1080 cursor_client->DisableMouseEvents();
1083 BackingStore* RenderWidgetHostViewAura::AllocBackingStore(
1084 const gfx::Size& size) {
1085 return new BackingStoreAura(host_, size);
1088 void RenderWidgetHostViewAura::CopyFromCompositingSurface(
1089 const gfx::Rect& src_subrect,
1090 const gfx::Size& dst_size,
1091 const base::Callback<void(bool, const SkBitmap&)>& callback,
1092 const SkBitmap::Config config) {
1093 // Only ARGB888 and RGB565 supported as of now.
1094 bool format_support = ((config == SkBitmap::kRGB_565_Config) ||
1095 (config == SkBitmap::kARGB_8888_Config));
1096 if (!format_support) {
1097 DCHECK(format_support);
1098 callback.Run(false, SkBitmap());
1101 if (!CanCopyToBitmap()) {
1102 callback.Run(false, SkBitmap());
1106 const gfx::Size& dst_size_in_pixel = ConvertViewSizeToPixel(this, dst_size);
1107 scoped_ptr<cc::CopyOutputRequest> request =
1108 cc::CopyOutputRequest::CreateRequest(base::Bind(
1109 &RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult,
1113 gfx::Rect src_subrect_in_pixel =
1114 ConvertRectToPixel(current_device_scale_factor_, src_subrect);
1115 request->set_area(src_subrect_in_pixel);
1116 RequestCopyOfOutput(request.Pass());
1119 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
1120 const gfx::Rect& src_subrect,
1121 const scoped_refptr<media::VideoFrame>& target,
1122 const base::Callback<void(bool)>& callback) {
1123 if (!CanCopyToVideoFrame()) {
1124 callback.Run(false);
1128 // Try get a texture to reuse.
1129 scoped_refptr<OwnedMailbox> subscriber_texture;
1130 if (frame_subscriber_) {
1131 if (!idle_frame_subscriber_textures_.empty()) {
1132 subscriber_texture = idle_frame_subscriber_textures_.back();
1133 idle_frame_subscriber_textures_.pop_back();
1134 } else if (GLHelper* helper =
1135 ImageTransportFactory::GetInstance()->GetGLHelper()) {
1136 subscriber_texture = new OwnedMailbox(helper);
1138 if (subscriber_texture.get())
1139 active_frame_subscriber_textures_.insert(subscriber_texture.get());
1142 scoped_ptr<cc::CopyOutputRequest> request =
1143 cc::CopyOutputRequest::CreateRequest(base::Bind(
1144 &RenderWidgetHostViewAura::
1145 CopyFromCompositingSurfaceHasResultForVideo,
1146 AsWeakPtr(), // For caching the ReadbackYUVInterface on this class.
1150 gfx::Rect src_subrect_in_pixel =
1151 ConvertRectToPixel(current_device_scale_factor_, src_subrect);
1152 request->set_area(src_subrect_in_pixel);
1153 if (subscriber_texture.get()) {
1154 request->SetTextureMailbox(
1155 cc::TextureMailbox(subscriber_texture->mailbox(),
1156 subscriber_texture->target(),
1157 subscriber_texture->sync_point()));
1159 RequestCopyOfOutput(request.Pass());
1162 bool RenderWidgetHostViewAura::CanCopyToBitmap() const {
1163 return GetCompositor() && window_->layer()->has_external_content();
1166 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
1167 return GetCompositor() &&
1168 window_->layer()->has_external_content() &&
1169 host_->is_accelerated_compositing_active();
1172 bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
1176 void RenderWidgetHostViewAura::BeginFrameSubscription(
1177 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1178 frame_subscriber_ = subscriber.Pass();
1181 void RenderWidgetHostViewAura::EndFrameSubscription() {
1182 idle_frame_subscriber_textures_.clear();
1183 frame_subscriber_.reset();
1186 void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() {
1187 // Delay processing the state change until we either get a software frame if
1188 // switching to software mode or receive a buffers swapped notification
1189 // if switching to accelerated mode.
1190 // Sometimes (e.g. on a page load) the renderer will spuriously disable then
1191 // re-enable accelerated compositing, causing us to flash.
1192 // TODO(piman): factor the enable/disable accelerated compositing message into
1193 // the UpdateRect/AcceleratedSurfaceBuffersSwapped messages so that we have
1194 // fewer inconsistent temporary states.
1195 accelerated_compositing_state_changed_ = true;
1198 void RenderWidgetHostViewAura::AcceleratedSurfaceInitialized(int host_id,
1202 bool RenderWidgetHostViewAura::ShouldSkipFrame(gfx::Size size_in_dip) const {
1203 if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
1204 can_lock_compositor_ == NO_PENDING_COMMIT ||
1205 !resize_lock_.get())
1208 return size_in_dip != resize_lock_->expected_size();
1211 void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
1212 if (HasDisplayPropertyChanged(window_))
1213 host_->InvalidateScreenInfo();
1215 // Don't recursively call SetBounds if this bounds update is the result of
1216 // a Window::SetBoundsInternal call.
1217 if (!in_bounds_changed_)
1218 window_->SetBounds(rect);
1219 host_->WasResized();
1220 MaybeCreateResizeLock();
1221 if (touch_editing_client_) {
1222 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
1223 selection_focus_rect_);
1226 // Create the legacy dummy window which corresponds to the bounds of the
1227 // webcontents. This will be passed as the container window for windowless
1229 // Plugins like Flash assume the container window which is returned via the
1230 // NPNVnetscapeWindow property corresponds to the bounds of the webpage.
1231 // This is not true in Aura where we have only HWND which is the main Aura
1232 // window. If we return this window to plugins like Flash then it causes the
1233 // coordinate translations done by these plugins to break.
1234 // Additonally the legacy dummy window is needed for accessibility and for
1235 // scrolling to work in legacy drivers for trackpoints/trackpads, etc.
1236 if (GetNativeViewId()) {
1237 if (!legacy_render_widget_host_HWND_) {
1238 legacy_render_widget_host_HWND_ = LegacyRenderWidgetHostHWND::Create(
1239 reinterpret_cast<HWND>(GetNativeViewId()));
1241 if (legacy_render_widget_host_HWND_) {
1242 legacy_render_widget_host_HWND_->SetBounds(
1243 window_->GetBoundsInRootWindow());
1249 void RenderWidgetHostViewAura::CheckResizeLock() {
1250 if (!resize_lock_ || resize_lock_->expected_size() != current_frame_size_)
1253 // Since we got the size we were looking for, unlock the compositor. But delay
1254 // the release of the lock until we've kicked a frame with the new texture, to
1255 // avoid resizing the UI before we have a chance to draw a "good" frame.
1256 resize_lock_->UnlockCompositor();
1257 ui::Compositor* compositor = GetCompositor();
1259 if (!compositor->HasObserver(this))
1260 compositor->AddObserver(this);
1264 void RenderWidgetHostViewAura::UpdateExternalTexture() {
1265 // Delay processing accelerated compositing state change till here where we
1266 // act upon the state change. (Clear the external texture if switching to
1267 // software mode or set the external texture if going to accelerated mode).
1268 if (accelerated_compositing_state_changed_)
1269 accelerated_compositing_state_changed_ = false;
1271 bool is_compositing_active = host_->is_accelerated_compositing_active();
1272 if (is_compositing_active && current_surface_.get()) {
1273 window_->layer()->SetExternalTexture(current_surface_.get());
1274 current_frame_size_ = ConvertSizeToDIP(
1275 current_surface_->device_scale_factor(), current_surface_->size());
1277 software_frame_manager_->DiscardCurrentFrame();
1278 } else if (is_compositing_active &&
1279 software_frame_manager_->HasCurrentFrame()) {
1280 cc::TextureMailbox mailbox;
1281 scoped_ptr<cc::SingleReleaseCallback> callback;
1282 software_frame_manager_->GetCurrentFrameMailbox(&mailbox, &callback);
1283 window_->layer()->SetTextureMailbox(mailbox,
1285 last_swapped_surface_scale_factor_);
1286 current_frame_size_ = ConvertSizeToDIP(last_swapped_surface_scale_factor_,
1287 mailbox.shared_memory_size());
1290 window_->layer()->SetShowPaintedContent();
1291 resize_lock_.reset();
1292 host_->WasResized();
1293 software_frame_manager_->DiscardCurrentFrame();
1297 bool RenderWidgetHostViewAura::SwapBuffersPrepare(
1298 const gfx::Rect& surface_rect,
1299 float surface_scale_factor,
1300 const gfx::Rect& damage_rect,
1301 const gpu::Mailbox& mailbox,
1302 const BufferPresentedCallback& ack_callback) {
1303 if (last_swapped_surface_size_ != surface_rect.size()) {
1304 // The surface could have shrunk since we skipped an update, in which
1305 // case we can expect a full update.
1306 DLOG_IF(ERROR, damage_rect != surface_rect) << "Expected full damage rect";
1307 skipped_damage_.setEmpty();
1308 last_swapped_surface_size_ = surface_rect.size();
1309 last_swapped_surface_scale_factor_ = surface_scale_factor;
1312 if (ShouldSkipFrame(ConvertSizeToDIP(surface_scale_factor,
1313 surface_rect.size())) ||
1315 skipped_damage_.op(RectToSkIRect(damage_rect), SkRegion::kUnion_Op);
1316 ack_callback.Run(true, scoped_refptr<ui::Texture>());
1320 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
1322 factory->CreateTransportClient(surface_scale_factor);
1323 if (!current_surface_.get()) {
1324 LOG(ERROR) << "Failed to create ImageTransport texture";
1325 ack_callback.Run(true, scoped_refptr<ui::Texture>());
1329 current_surface_->Consume(mailbox, surface_rect.size());
1330 released_front_lock_ = NULL;
1331 UpdateExternalTexture();
1336 void RenderWidgetHostViewAura::SwapBuffersCompleted(
1337 const BufferPresentedCallback& ack_callback,
1338 const scoped_refptr<ui::Texture>& texture_to_return) {
1339 ui::Compositor* compositor = GetCompositor();
1341 ack_callback.Run(false, texture_to_return);
1343 AddOnCommitCallbackAndDisableLocks(
1344 base::Bind(ack_callback, false, texture_to_return));
1347 DidReceiveFrameFromRenderer();
1350 void RenderWidgetHostViewAura::DidReceiveFrameFromRenderer() {
1351 if (frame_subscriber() && CanCopyToVideoFrame()) {
1352 const base::TimeTicks present_time = base::TimeTicks::Now();
1353 scoped_refptr<media::VideoFrame> frame;
1354 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
1355 if (frame_subscriber()->ShouldCaptureFrame(present_time,
1356 &frame, &callback)) {
1357 CopyFromCompositingSurfaceToVideoFrame(
1358 gfx::Rect(current_frame_size_),
1360 base::Bind(callback, present_time));
1366 void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
1367 const std::vector<gfx::Rect>& rects) {
1368 // Check this before setting constrained_rects_, so that next time they're set
1369 // and we have a root window we don't early return.
1370 if (!window_->GetDispatcher())
1373 if (rects == constrained_rects_)
1376 constrained_rects_ = rects;
1378 HWND parent = window_->GetDispatcher()->host()->GetAcceleratedWidget();
1379 CutoutRectsParams params;
1380 params.widget = this;
1381 params.cutout_rects = constrained_rects_;
1382 params.geometry = &plugin_window_moves_;
1383 LPARAM lparam = reinterpret_cast<LPARAM>(¶ms);
1384 EnumChildWindows(parent, SetCutoutRectsCallback, lparam);
1388 void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
1389 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
1391 BufferPresentedCallback ack_callback = base::Bind(
1392 &AcknowledgeBufferForGpu,
1393 params_in_pixel.route_id,
1395 params_in_pixel.mailbox);
1396 BuffersSwapped(params_in_pixel.size,
1397 gfx::Rect(params_in_pixel.size),
1398 params_in_pixel.scale_factor,
1399 params_in_pixel.mailbox,
1400 params_in_pixel.latency_info,
1404 void RenderWidgetHostViewAura::SwapDelegatedFrame(
1405 uint32 output_surface_id,
1406 scoped_ptr<cc::DelegatedFrameData> frame_data,
1407 float frame_device_scale_factor,
1408 const std::vector<ui::LatencyInfo>& latency_info) {
1409 DCHECK_NE(0u, frame_data->render_pass_list.size());
1411 cc::RenderPass* root_pass = frame_data->render_pass_list.back();
1413 gfx::Size frame_size = root_pass->output_rect.size();
1414 gfx::Size frame_size_in_dip =
1415 ConvertSizeToDIP(frame_device_scale_factor, frame_size);
1417 gfx::Rect damage_rect = gfx::ToEnclosingRect(root_pass->damage_rect);
1418 damage_rect.Intersect(gfx::Rect(frame_size));
1419 gfx::Rect damage_rect_in_dip =
1420 ConvertRectToDIP(frame_device_scale_factor, damage_rect);
1422 software_frame_manager_->DiscardCurrentFrame();
1424 if (ShouldSkipFrame(frame_size_in_dip)) {
1425 cc::CompositorFrameAck ack;
1426 cc::TransferableResource::ReturnResources(frame_data->resource_list,
1428 RenderWidgetHostImpl::SendSwapCompositorFrameAck(
1429 host_->GetRoutingID(), output_surface_id,
1430 host_->GetProcess()->GetID(), ack);
1431 skipped_frames_ = true;
1435 if (skipped_frames_) {
1436 skipped_frames_ = false;
1437 damage_rect = gfx::Rect(frame_size);
1438 damage_rect_in_dip = gfx::Rect(frame_size_in_dip);
1440 // Give the same damage rect to the compositor.
1441 cc::RenderPass* root_pass = frame_data->render_pass_list.back();
1442 root_pass->damage_rect = damage_rect;
1445 if (output_surface_id != last_output_surface_id_) {
1446 // Resource ids are scoped by the output surface.
1447 // If the originating output surface doesn't match the last one, it
1448 // indicates the renderer's output surface may have been recreated, in which
1449 // case we should recreate the DelegatedRendererLayer, to avoid matching
1450 // resources from the old one with resources from the new one which would
1451 // have the same id. Changing the layer to showing painted content destroys
1452 // the DelegatedRendererLayer.
1453 EvictDelegatedFrame();
1455 // Drop the cc::DelegatedFrameResourceCollection so that we will not return
1456 // any resources from the old output surface with the new output surface id.
1457 if (resource_collection_.get()) {
1458 resource_collection_->SetClient(NULL);
1460 if (resource_collection_->LoseAllResources())
1461 SendReturnedDelegatedResources(last_output_surface_id_);
1463 resource_collection_ = NULL;
1465 last_output_surface_id_ = output_surface_id;
1467 if (frame_size.IsEmpty()) {
1468 DCHECK_EQ(0u, frame_data->resource_list.size());
1469 EvictDelegatedFrame();
1471 if (!resource_collection_) {
1472 resource_collection_ = new cc::DelegatedFrameResourceCollection;
1473 resource_collection_->SetClient(this);
1475 // If the physical frame size changes, we need a new |frame_provider_|. If
1476 // the physical frame size is the same, but the size in DIP changed, we
1477 // need to adjust the scale at which the frames will be drawn, and we do
1478 // this by making a new |frame_provider_| also to ensure the scale change
1479 // is presented in sync with the new frame content.
1480 if (!frame_provider_.get() || frame_size != frame_provider_->frame_size() ||
1481 frame_size_in_dip != current_frame_size_) {
1482 frame_provider_ = new cc::DelegatedFrameProvider(
1483 resource_collection_.get(), frame_data.Pass());
1484 window_->layer()->SetShowDelegatedContent(frame_provider_.get(),
1487 frame_provider_->SetFrameData(frame_data.Pass());
1490 released_front_lock_ = NULL;
1491 current_frame_size_ = frame_size_in_dip;
1494 window_->SchedulePaintInRect(damage_rect_in_dip);
1496 pending_delegated_ack_count_++;
1498 ui::Compositor* compositor = GetCompositor();
1500 SendDelegatedFrameAck(output_surface_id);
1502 for (size_t i = 0; i < latency_info.size(); i++)
1503 compositor->SetLatencyInfo(latency_info[i]);
1504 AddOnCommitCallbackAndDisableLocks(
1505 base::Bind(&RenderWidgetHostViewAura::SendDelegatedFrameAck,
1507 output_surface_id));
1509 DidReceiveFrameFromRenderer();
1510 if (frame_provider_.get())
1511 delegated_frame_evictor_->SwappedFrame(!host_->is_hidden());
1512 // Note: the frame may have been evicted immediately.
1515 void RenderWidgetHostViewAura::SendDelegatedFrameAck(uint32 output_surface_id) {
1516 cc::CompositorFrameAck ack;
1517 if (resource_collection_)
1518 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
1519 RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(),
1521 host_->GetProcess()->GetID(),
1523 DCHECK_GT(pending_delegated_ack_count_, 0);
1524 pending_delegated_ack_count_--;
1527 void RenderWidgetHostViewAura::UnusedResourcesAreAvailable() {
1528 if (pending_delegated_ack_count_)
1531 SendReturnedDelegatedResources(last_output_surface_id_);
1534 void RenderWidgetHostViewAura::SendReturnedDelegatedResources(
1535 uint32 output_surface_id) {
1536 DCHECK(resource_collection_);
1538 cc::CompositorFrameAck ack;
1539 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
1540 DCHECK(!ack.resources.empty());
1542 RenderWidgetHostImpl::SendReclaimCompositorResources(
1543 host_->GetRoutingID(),
1545 host_->GetProcess()->GetID(),
1549 void RenderWidgetHostViewAura::EvictDelegatedFrame() {
1550 window_->layer()->SetShowPaintedContent();
1551 frame_provider_ = NULL;
1552 delegated_frame_evictor_->DiscardedFrame();
1555 void RenderWidgetHostViewAura::SwapSoftwareFrame(
1556 uint32 output_surface_id,
1557 scoped_ptr<cc::SoftwareFrameData> frame_data,
1558 float frame_device_scale_factor,
1559 const std::vector<ui::LatencyInfo>& latency_info) {
1560 const gfx::Size& frame_size = frame_data->size;
1561 const gfx::Rect& damage_rect = frame_data->damage_rect;
1562 gfx::Size frame_size_in_dip =
1563 ConvertSizeToDIP(frame_device_scale_factor, frame_size);
1564 if (ShouldSkipFrame(frame_size_in_dip)) {
1565 ReleaseSoftwareFrame(output_surface_id, frame_data->id);
1566 SendSoftwareFrameAck(output_surface_id);
1570 if (!software_frame_manager_->SwapToNewFrame(
1573 frame_device_scale_factor,
1574 host_->GetProcess()->GetHandle())) {
1575 ReleaseSoftwareFrame(output_surface_id, frame_data->id);
1576 SendSoftwareFrameAck(output_surface_id);
1580 if (last_swapped_surface_size_ != frame_size) {
1581 DLOG_IF(ERROR, damage_rect != gfx::Rect(frame_size))
1582 << "Expected full damage rect";
1584 last_swapped_surface_size_ = frame_size;
1585 last_swapped_surface_scale_factor_ = frame_device_scale_factor;
1587 cc::TextureMailbox mailbox;
1588 scoped_ptr<cc::SingleReleaseCallback> callback;
1589 software_frame_manager_->GetCurrentFrameMailbox(&mailbox, &callback);
1590 DCHECK(mailbox.IsSharedMemory());
1591 current_frame_size_ = frame_size_in_dip;
1593 released_front_lock_ = NULL;
1595 window_->layer()->SetTextureMailbox(mailbox,
1597 frame_device_scale_factor);
1598 window_->SchedulePaintInRect(
1599 ConvertRectToDIP(frame_device_scale_factor, damage_rect));
1601 ui::Compositor* compositor = GetCompositor();
1603 for (size_t i = 0; i < latency_info.size(); i++)
1604 compositor->SetLatencyInfo(latency_info[i]);
1605 AddOnCommitCallbackAndDisableLocks(
1606 base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck,
1608 output_surface_id));
1610 SendSoftwareFrameAck(output_surface_id);
1612 DidReceiveFrameFromRenderer();
1614 software_frame_manager_->SwapToNewFrameComplete(!host_->is_hidden());
1617 void RenderWidgetHostViewAura::SendSoftwareFrameAck(uint32 output_surface_id) {
1618 unsigned software_frame_id = 0;
1619 if (released_software_frame_ &&
1620 released_software_frame_->output_surface_id == output_surface_id) {
1621 software_frame_id = released_software_frame_->frame_id;
1622 released_software_frame_.reset();
1625 cc::CompositorFrameAck ack;
1626 ack.last_software_frame_id = software_frame_id;
1627 RenderWidgetHostImpl::SendSwapCompositorFrameAck(
1628 host_->GetRoutingID(), output_surface_id,
1629 host_->GetProcess()->GetID(), ack);
1630 SendReclaimSoftwareFrames();
1633 void RenderWidgetHostViewAura::SendReclaimSoftwareFrames() {
1634 if (!released_software_frame_)
1636 cc::CompositorFrameAck ack;
1637 ack.last_software_frame_id = released_software_frame_->frame_id;
1638 RenderWidgetHostImpl::SendReclaimCompositorResources(
1639 host_->GetRoutingID(),
1640 released_software_frame_->output_surface_id,
1641 host_->GetProcess()->GetID(),
1643 released_software_frame_.reset();
1646 void RenderWidgetHostViewAura::ReleaseSoftwareFrame(
1647 uint32 output_surface_id,
1648 unsigned software_frame_id) {
1649 SendReclaimSoftwareFrames();
1650 DCHECK(!released_software_frame_);
1651 released_software_frame_.reset(new ReleasedFrameInfo(
1652 output_surface_id, software_frame_id));
1655 void RenderWidgetHostViewAura::OnSwapCompositorFrame(
1656 uint32 output_surface_id,
1657 scoped_ptr<cc::CompositorFrame> frame) {
1658 TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
1659 if (frame->delegated_frame_data) {
1660 SwapDelegatedFrame(output_surface_id,
1661 frame->delegated_frame_data.Pass(),
1662 frame->metadata.device_scale_factor,
1663 frame->metadata.latency_info);
1667 if (frame->software_frame_data) {
1668 SwapSoftwareFrame(output_surface_id,
1669 frame->software_frame_data.Pass(),
1670 frame->metadata.device_scale_factor,
1671 frame->metadata.latency_info);
1675 if (!frame->gl_frame_data || frame->gl_frame_data->mailbox.IsZero())
1678 BufferPresentedCallback ack_callback = base::Bind(
1679 &SendCompositorFrameAck,
1680 host_->GetRoutingID(), output_surface_id, host_->GetProcess()->GetID(),
1681 frame->gl_frame_data->mailbox, frame->gl_frame_data->size);
1683 if (!frame->gl_frame_data->sync_point) {
1684 LOG(ERROR) << "CompositorFrame without sync point. Skipping frame...";
1685 ack_callback.Run(true, scoped_refptr<ui::Texture>());
1689 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
1690 gl_helper->WaitSyncPoint(frame->gl_frame_data->sync_point);
1692 BuffersSwapped(frame->gl_frame_data->size,
1693 frame->gl_frame_data->sub_buffer_rect,
1694 frame->metadata.device_scale_factor,
1695 frame->gl_frame_data->mailbox,
1696 frame->metadata.latency_info,
1701 void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
1702 gfx::NativeViewAccessible accessible_parent) {
1703 if (GetBrowserAccessibilityManager()) {
1704 GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerWin()
1705 ->set_parent_iaccessible(accessible_parent);
1709 gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
1711 if (legacy_render_widget_host_HWND_) {
1712 return reinterpret_cast<gfx::NativeViewId>(
1713 legacy_render_widget_host_HWND_->hwnd());
1719 void RenderWidgetHostViewAura::BuffersSwapped(
1720 const gfx::Size& surface_size,
1721 const gfx::Rect& damage_rect,
1722 float surface_scale_factor,
1723 const gpu::Mailbox& mailbox,
1724 const std::vector<ui::LatencyInfo>& latency_info,
1725 const BufferPresentedCallback& ack_callback) {
1726 scoped_refptr<ui::Texture> previous_texture(current_surface_);
1727 const gfx::Rect surface_rect = gfx::Rect(surface_size);
1728 software_frame_manager_->DiscardCurrentFrame();
1730 if (!SwapBuffersPrepare(surface_rect,
1731 surface_scale_factor,
1738 SkRegion damage(RectToSkIRect(damage_rect));
1739 if (!skipped_damage_.isEmpty()) {
1740 damage.op(skipped_damage_, SkRegion::kUnion_Op);
1741 skipped_damage_.setEmpty();
1744 DCHECK(surface_rect.Contains(SkIRectToRect(damage.getBounds())));
1745 ui::Texture* current_texture = current_surface_.get();
1747 const gfx::Size surface_size_in_pixel = surface_size;
1748 DLOG_IF(ERROR, previous_texture.get() &&
1749 previous_texture->size() != current_texture->size() &&
1750 SkIRectToRect(damage.getBounds()) != surface_rect) <<
1751 "Expected full damage rect after size change";
1752 if (previous_texture.get() && !previous_damage_.isEmpty() &&
1753 previous_texture->size() == current_texture->size()) {
1754 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
1755 GLHelper* gl_helper = factory->GetGLHelper();
1756 gl_helper->CopySubBufferDamage(
1757 current_texture->PrepareTexture(),
1758 previous_texture->PrepareTexture(),
1762 previous_damage_ = damage;
1764 ui::Compositor* compositor = GetCompositor();
1766 // Co-ordinates come in OpenGL co-ordinate space.
1767 // We need to convert to layer space.
1768 gfx::Rect rect_to_paint =
1769 ConvertRectToDIP(surface_scale_factor,
1770 gfx::Rect(damage_rect.x(),
1771 surface_size_in_pixel.height() -
1772 damage_rect.y() - damage_rect.height(),
1773 damage_rect.width(),
1774 damage_rect.height()));
1776 // Damage may not have been DIP aligned, so inflate damage to compensate
1777 // for any round-off error.
1778 rect_to_paint.Inset(-1, -1);
1779 rect_to_paint.Intersect(window_->bounds());
1781 window_->SchedulePaintInRect(rect_to_paint);
1782 for (size_t i = 0; i < latency_info.size(); i++)
1783 compositor->SetLatencyInfo(latency_info[i]);
1786 SwapBuffersCompleted(ack_callback, previous_texture);
1789 void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
1790 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel,
1792 gfx::Rect damage_rect(params_in_pixel.x,
1794 params_in_pixel.width,
1795 params_in_pixel.height);
1796 BufferPresentedCallback ack_callback =
1797 base::Bind(&AcknowledgeBufferForGpu,
1798 params_in_pixel.route_id,
1800 params_in_pixel.mailbox);
1801 BuffersSwapped(params_in_pixel.surface_size,
1803 params_in_pixel.surface_scale_factor,
1804 params_in_pixel.mailbox,
1805 params_in_pixel.latency_info,
1809 void RenderWidgetHostViewAura::AcceleratedSurfaceSuspend() {
1812 void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() {
1813 // This really tells us to release the frontbuffer.
1814 if (current_surface_.get()) {
1815 ui::Compositor* compositor = GetCompositor();
1817 // We need to wait for a commit to clear to guarantee that all we
1818 // will not issue any more GL referencing the previous surface.
1819 AddOnCommitCallbackAndDisableLocks(
1820 base::Bind(&RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor,
1822 current_surface_)); // Hold a ref so the texture will not
1823 // get deleted until after commit.
1825 current_surface_ = NULL;
1826 UpdateExternalTexture();
1830 bool RenderWidgetHostViewAura::HasAcceleratedSurface(
1831 const gfx::Size& desired_size) {
1832 // Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
1833 // matter what is returned here as GetBackingStore is the only caller of this
1834 // method. TODO(jbates) implement this if other Aura code needs it.
1838 void RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor(
1839 scoped_refptr<ui::Texture>) {
1843 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult(
1844 const gfx::Size& dst_size_in_pixel,
1845 const SkBitmap::Config config,
1846 const base::Callback<void(bool, const SkBitmap&)>& callback,
1847 scoped_ptr<cc::CopyOutputResult> result) {
1848 if (result->IsEmpty() || result->size().IsEmpty()) {
1849 callback.Run(false, SkBitmap());
1853 if (result->HasTexture()) {
1854 PrepareTextureCopyOutputResult(dst_size_in_pixel, config,
1860 DCHECK(result->HasBitmap());
1861 PrepareBitmapCopyOutputResult(dst_size_in_pixel, config, callback,
1865 static void CopyFromCompositingSurfaceFinished(
1866 const base::Callback<void(bool, const SkBitmap&)>& callback,
1867 scoped_ptr<cc::SingleReleaseCallback> release_callback,
1868 scoped_ptr<SkBitmap> bitmap,
1869 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
1871 bitmap_pixels_lock.reset();
1873 uint32 sync_point = 0;
1875 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
1876 sync_point = gl_helper->InsertSyncPoint();
1878 bool lost_resource = sync_point == 0;
1879 release_callback->Run(sync_point, lost_resource);
1881 callback.Run(result, *bitmap);
1885 void RenderWidgetHostViewAura::PrepareTextureCopyOutputResult(
1886 const gfx::Size& dst_size_in_pixel,
1887 const SkBitmap::Config config,
1888 const base::Callback<void(bool, const SkBitmap&)>& callback,
1889 scoped_ptr<cc::CopyOutputResult> result) {
1890 DCHECK(result->HasTexture());
1891 base::ScopedClosureRunner scoped_callback_runner(
1892 base::Bind(callback, false, SkBitmap()));
1894 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
1895 bitmap->setConfig(config,
1896 dst_size_in_pixel.width(), dst_size_in_pixel.height(),
1897 0, kOpaque_SkAlphaType);
1898 if (!bitmap->allocPixels())
1901 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
1902 GLHelper* gl_helper = factory->GetGLHelper();
1906 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
1907 new SkAutoLockPixels(*bitmap));
1908 uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
1910 cc::TextureMailbox texture_mailbox;
1911 scoped_ptr<cc::SingleReleaseCallback> release_callback;
1912 result->TakeTexture(&texture_mailbox, &release_callback);
1913 DCHECK(texture_mailbox.IsTexture());
1914 if (!texture_mailbox.IsTexture())
1917 ignore_result(scoped_callback_runner.Release());
1919 gl_helper->CropScaleReadbackAndCleanMailbox(
1920 texture_mailbox.mailbox(),
1921 texture_mailbox.sync_point(),
1923 gfx::Rect(result->size()),
1927 base::Bind(&CopyFromCompositingSurfaceFinished,
1929 base::Passed(&release_callback),
1930 base::Passed(&bitmap),
1931 base::Passed(&bitmap_pixels_lock)));
1935 void RenderWidgetHostViewAura::PrepareBitmapCopyOutputResult(
1936 const gfx::Size& dst_size_in_pixel,
1937 const SkBitmap::Config config,
1938 const base::Callback<void(bool, const SkBitmap&)>& callback,
1939 scoped_ptr<cc::CopyOutputResult> result) {
1940 if (config != SkBitmap::kARGB_8888_Config) {
1942 callback.Run(false, SkBitmap());
1945 DCHECK(result->HasBitmap());
1946 base::ScopedClosureRunner scoped_callback_runner(
1947 base::Bind(callback, false, SkBitmap()));
1949 scoped_ptr<SkBitmap> source = result->TakeBitmap();
1954 ignore_result(scoped_callback_runner.Release());
1956 SkBitmap bitmap = skia::ImageOperations::Resize(
1958 skia::ImageOperations::RESIZE_BEST,
1959 dst_size_in_pixel.width(),
1960 dst_size_in_pixel.height());
1961 callback.Run(true, bitmap);
1965 void RenderWidgetHostViewAura::ReturnSubscriberTexture(
1966 base::WeakPtr<RenderWidgetHostViewAura> rwhva,
1967 scoped_refptr<OwnedMailbox> subscriber_texture,
1968 uint32 sync_point) {
1969 if (!subscriber_texture.get())
1974 rwhva->active_frame_subscriber_textures_.count(subscriber_texture.get()),
1977 subscriber_texture->UpdateSyncPoint(sync_point);
1979 rwhva->active_frame_subscriber_textures_.erase(subscriber_texture.get());
1980 if (rwhva->frame_subscriber_ && subscriber_texture->texture_id())
1981 rwhva->idle_frame_subscriber_textures_.push_back(subscriber_texture);
1984 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinishedForVideo(
1985 base::WeakPtr<RenderWidgetHostViewAura> rwhva,
1986 const base::Callback<void(bool)>& callback,
1987 scoped_refptr<OwnedMailbox> subscriber_texture,
1988 scoped_ptr<cc::SingleReleaseCallback> release_callback,
1990 callback.Run(result);
1992 uint32 sync_point = 0;
1994 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
1995 sync_point = gl_helper->InsertSyncPoint();
1997 if (release_callback) {
1998 // A release callback means the texture came from the compositor, so there
1999 // should be no |subscriber_texture|.
2000 DCHECK(!subscriber_texture);
2001 bool lost_resource = sync_point == 0;
2002 release_callback->Run(sync_point, lost_resource);
2004 ReturnSubscriberTexture(rwhva, subscriber_texture, sync_point);
2008 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo(
2009 base::WeakPtr<RenderWidgetHostViewAura> rwhva,
2010 scoped_refptr<OwnedMailbox> subscriber_texture,
2011 scoped_refptr<media::VideoFrame> video_frame,
2012 const base::Callback<void(bool)>& callback,
2013 scoped_ptr<cc::CopyOutputResult> result) {
2014 base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
2015 base::ScopedClosureRunner scoped_return_subscriber_texture(
2016 base::Bind(&ReturnSubscriberTexture, rwhva, subscriber_texture, 0));
2020 if (result->IsEmpty())
2022 if (result->size().IsEmpty())
2025 // Compute the dest size we want after the letterboxing resize. Make the
2026 // coordinates and sizes even because we letterbox in YUV space
2027 // (see CopyRGBToVideoFrame). They need to be even for the UV samples to
2028 // line up correctly.
2029 // The video frame's coded_size() and the result's size() are both physical
2031 gfx::Rect region_in_frame =
2032 media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()),
2034 region_in_frame = gfx::Rect(region_in_frame.x() & ~1,
2035 region_in_frame.y() & ~1,
2036 region_in_frame.width() & ~1,
2037 region_in_frame.height() & ~1);
2038 if (region_in_frame.IsEmpty())
2041 if (!result->HasTexture()) {
2042 DCHECK(result->HasBitmap());
2043 scoped_ptr<SkBitmap> bitmap = result->TakeBitmap();
2044 // Scale the bitmap to the required size, if necessary.
2045 SkBitmap scaled_bitmap;
2046 if (result->size().width() != region_in_frame.width() ||
2047 result->size().height() != region_in_frame.height()) {
2048 skia::ImageOperations::ResizeMethod method =
2049 skia::ImageOperations::RESIZE_GOOD;
2050 scaled_bitmap = skia::ImageOperations::Resize(*bitmap.get(), method,
2051 region_in_frame.width(),
2052 region_in_frame.height());
2054 scaled_bitmap = *bitmap.get();
2058 SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap);
2060 media::CopyRGBToVideoFrame(
2061 reinterpret_cast<uint8*>(scaled_bitmap.getPixels()),
2062 scaled_bitmap.rowBytes(),
2066 ignore_result(scoped_callback_runner.Release());
2071 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
2072 GLHelper* gl_helper = factory->GetGLHelper();
2075 if (subscriber_texture.get() && !subscriber_texture->texture_id())
2078 cc::TextureMailbox texture_mailbox;
2079 scoped_ptr<cc::SingleReleaseCallback> release_callback;
2080 result->TakeTexture(&texture_mailbox, &release_callback);
2081 DCHECK(texture_mailbox.IsTexture());
2082 if (!texture_mailbox.IsTexture())
2085 gfx::Rect result_rect(result->size());
2087 content::ReadbackYUVInterface* yuv_readback_pipeline =
2088 rwhva->yuv_readback_pipeline_.get();
2089 if (yuv_readback_pipeline == NULL ||
2090 yuv_readback_pipeline->scaler()->SrcSize() != result_rect.size() ||
2091 yuv_readback_pipeline->scaler()->SrcSubrect() != result_rect ||
2092 yuv_readback_pipeline->scaler()->DstSize() != region_in_frame.size()) {
2093 GLHelper::ScalerQuality quality = GLHelper::SCALER_QUALITY_FAST;
2094 std::string quality_switch = switches::kTabCaptureDownscaleQuality;
2095 // If we're scaling up, we can use the "best" quality.
2096 if (result_rect.size().width() < region_in_frame.size().width() &&
2097 result_rect.size().height() < region_in_frame.size().height())
2098 quality_switch = switches::kTabCaptureUpscaleQuality;
2100 std::string switch_value =
2101 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(quality_switch);
2102 if (switch_value == "fast")
2103 quality = GLHelper::SCALER_QUALITY_FAST;
2104 else if (switch_value == "good")
2105 quality = GLHelper::SCALER_QUALITY_GOOD;
2106 else if (switch_value == "best")
2107 quality = GLHelper::SCALER_QUALITY_BEST;
2109 rwhva->yuv_readback_pipeline_.reset(
2110 gl_helper->CreateReadbackPipelineYUV(quality,
2113 video_frame->coded_size(),
2117 yuv_readback_pipeline = rwhva->yuv_readback_pipeline_.get();
2120 ignore_result(scoped_callback_runner.Release());
2121 ignore_result(scoped_return_subscriber_texture.Release());
2122 base::Callback<void(bool result)> finished_callback = base::Bind(
2123 &RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinishedForVideo,
2127 base::Passed(&release_callback));
2128 yuv_readback_pipeline->ReadbackYUV(texture_mailbox.mailbox(),
2129 texture_mailbox.sync_point(),
2134 void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) {
2135 GetScreenInfoForWindow(results, window_->GetRootWindow() ? window_ : NULL);
2138 gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
2140 // aura::Window::GetBoundsInScreen doesn't take non-client area into
2142 RECT window_rect = {0};
2144 aura::Window* top_level = window_->GetToplevelWindow();
2145 aura::WindowEventDispatcher* dispatcher = top_level->GetDispatcher();
2147 return top_level->GetBoundsInScreen();
2148 HWND hwnd = dispatcher->host()->GetAcceleratedWidget();
2149 ::GetWindowRect(hwnd, &window_rect);
2150 gfx::Rect rect(window_rect);
2152 // Maximized windows are outdented from the work area by the frame thickness
2153 // even though this "frame" is not painted. This confuses code (and people)
2154 // that think of a maximized window as corresponding exactly to the work area.
2155 // Correct for this by subtracting the frame thickness back off.
2156 if (::IsZoomed(hwnd)) {
2157 rect.Inset(GetSystemMetrics(SM_CXSIZEFRAME),
2158 GetSystemMetrics(SM_CYSIZEFRAME));
2161 return gfx::win::ScreenToDIPRect(rect);
2163 return window_->GetToplevelWindow()->GetBoundsInScreen();
2167 void RenderWidgetHostViewAura::GestureEventAck(
2168 const blink::WebGestureEvent& event,
2169 InputEventAckState ack_result) {
2170 if (touch_editing_client_)
2171 touch_editing_client_->GestureEventAck(event.type);
2174 void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
2175 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
2176 ScopedVector<ui::TouchEvent> events;
2177 if (!MakeUITouchEventsFromWebTouchEvents(touch, &events,
2178 SCREEN_COORDINATES))
2181 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
2182 // |dispatcher| is NULL during tests.
2186 ui::EventResult result = (ack_result ==
2187 INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
2188 for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
2189 end = events.end(); iter != end; ++iter) {
2190 dispatcher->ProcessedTouchEvent((*iter), window_, result);
2194 scoped_ptr<SyntheticGestureTarget>
2195 RenderWidgetHostViewAura::CreateSyntheticGestureTarget() {
2196 return scoped_ptr<SyntheticGestureTarget>(
2197 new SyntheticGestureTargetAura(host_));
2200 void RenderWidgetHostViewAura::SetHasHorizontalScrollbar(
2201 bool has_horizontal_scrollbar) {
2202 // Not needed. Mac-only.
2205 void RenderWidgetHostViewAura::SetScrollOffsetPinning(
2206 bool is_pinned_to_left, bool is_pinned_to_right) {
2207 // Not needed. Mac-only.
2210 void RenderWidgetHostViewAura::CreateBrowserAccessibilityManagerIfNeeded() {
2211 if (GetBrowserAccessibilityManager())
2214 BrowserAccessibilityManager* manager = NULL;
2216 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
2219 HWND hwnd = dispatcher->host()->GetAcceleratedWidget();
2221 // The accessible_parent may be NULL at this point. The WebContents will pass
2222 // it down to this instance (by way of the RenderViewHost and
2223 // RenderWidgetHost) when it is known. This instance will then set it on its
2224 // BrowserAccessibilityManager.
2225 gfx::NativeViewAccessible accessible_parent =
2226 host_->GetParentNativeViewAccessible();
2228 if (legacy_render_widget_host_HWND_) {
2229 manager = new BrowserAccessibilityManagerWin(
2230 legacy_render_widget_host_HWND_.get(), accessible_parent,
2231 BrowserAccessibilityManagerWin::GetEmptyDocument(), this);
2234 manager = BrowserAccessibilityManager::Create(
2235 BrowserAccessibilityManager::GetEmptyDocument(), this);
2237 SetBrowserAccessibilityManager(manager);
2240 gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
2241 return ImageTransportFactory::GetInstance()->GetSharedSurfaceHandle();
2244 bool RenderWidgetHostViewAura::LockMouse() {
2245 aura::Window* root_window = window_->GetRootWindow();
2252 mouse_locked_ = true;
2253 #if !defined(OS_WIN)
2254 window_->SetCapture();
2256 aura::client::CursorClient* cursor_client =
2257 aura::client::GetCursorClient(root_window);
2258 if (cursor_client) {
2259 cursor_client->HideCursor();
2260 cursor_client->LockCursor();
2263 if (ShouldMoveToCenter()) {
2264 synthetic_move_sent_ = true;
2265 window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
2267 tooltip_disabler_.reset(new aura::client::ScopedTooltipDisabler(root_window));
2269 root_window->GetDispatcher()->host()->ConfineCursorToRootWindow();
2273 void RenderWidgetHostViewAura::UnlockMouse() {
2274 tooltip_disabler_.reset();
2276 aura::Window* root_window = window_->GetRootWindow();
2277 if (!mouse_locked_ || !root_window)
2280 mouse_locked_ = false;
2282 #if !defined(OS_WIN)
2283 window_->ReleaseCapture();
2285 window_->MoveCursorTo(unlocked_mouse_position_);
2286 aura::client::CursorClient* cursor_client =
2287 aura::client::GetCursorClient(root_window);
2288 if (cursor_client) {
2289 cursor_client->UnlockCursor();
2290 cursor_client->ShowCursor();
2293 host_->LostMouseLock();
2294 root_window->GetDispatcher()->host()->UnConfineCursor();
2297 ////////////////////////////////////////////////////////////////////////////////
2298 // RenderWidgetHostViewAura, ui::TextInputClient implementation:
2299 void RenderWidgetHostViewAura::SetCompositionText(
2300 const ui::CompositionText& composition) {
2304 // ui::CompositionUnderline should be identical to
2305 // blink::WebCompositionUnderline, so that we can do reinterpret_cast safely.
2306 COMPILE_ASSERT(sizeof(ui::CompositionUnderline) ==
2307 sizeof(blink::WebCompositionUnderline),
2308 ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
2310 // TODO(suzhe): convert both renderer_host and renderer to use
2311 // ui::CompositionText.
2312 const std::vector<blink::WebCompositionUnderline>& underlines =
2313 reinterpret_cast<const std::vector<blink::WebCompositionUnderline>&>(
2314 composition.underlines);
2316 // TODO(suzhe): due to a bug of webkit, we can't use selection range with
2317 // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
2318 host_->ImeSetComposition(composition.text, underlines,
2319 composition.selection.end(),
2320 composition.selection.end());
2322 has_composition_text_ = !composition.text.empty();
2325 void RenderWidgetHostViewAura::ConfirmCompositionText() {
2326 if (host_ && has_composition_text_) {
2327 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
2330 has_composition_text_ = false;
2333 void RenderWidgetHostViewAura::ClearCompositionText() {
2334 if (host_ && has_composition_text_)
2335 host_->ImeCancelComposition();
2336 has_composition_text_ = false;
2339 void RenderWidgetHostViewAura::InsertText(const base::string16& text) {
2340 DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
2342 host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false);
2343 has_composition_text_ = false;
2346 void RenderWidgetHostViewAura::InsertChar(base::char16 ch, int flags) {
2347 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
2348 popup_child_host_view_->InsertChar(ch, flags);
2352 // Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547
2353 if (host_ && (accept_return_character_ || ch != ui::VKEY_RETURN)) {
2354 double now = ui::EventTimeForNow().InSecondsF();
2355 // Send a blink::WebInputEvent::Char event to |host_|.
2356 NativeWebKeyboardEvent webkit_event(ui::ET_KEY_PRESSED,
2361 host_->ForwardKeyboardEvent(webkit_event);
2365 gfx::NativeWindow RenderWidgetHostViewAura::GetAttachedWindow() const {
2369 ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const {
2370 return text_input_type_;
2373 ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
2374 return text_input_mode_;
2377 bool RenderWidgetHostViewAura::CanComposeInline() const {
2378 return can_compose_inline_;
2381 gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(
2382 const gfx::Rect& rect) const {
2383 gfx::Point origin = rect.origin();
2384 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
2386 aura::Window* root_window = window_->GetRootWindow();
2389 aura::client::ScreenPositionClient* screen_position_client =
2390 aura::client::GetScreenPositionClient(root_window);
2391 if (!screen_position_client)
2393 screen_position_client->ConvertPointToScreen(window_, &origin);
2394 screen_position_client->ConvertPointToScreen(window_, &end);
2395 return gfx::Rect(origin.x(),
2397 end.x() - origin.x(),
2398 end.y() - origin.y());
2401 gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
2402 const gfx::Rect& rect) const {
2403 gfx::Point origin = rect.origin();
2404 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
2406 aura::Window* root_window = window_->GetRootWindow();
2408 aura::client::ScreenPositionClient* screen_position_client =
2409 aura::client::GetScreenPositionClient(root_window);
2410 screen_position_client->ConvertPointFromScreen(window_, &origin);
2411 screen_position_client->ConvertPointFromScreen(window_, &end);
2412 return gfx::Rect(origin.x(),
2414 end.x() - origin.x(),
2415 end.y() - origin.y());
2421 gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const {
2422 const gfx::Rect rect =
2423 gfx::UnionRects(selection_anchor_rect_, selection_focus_rect_);
2424 return ConvertRectToScreen(rect);
2427 bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(
2429 gfx::Rect* rect) const {
2431 if (index >= composition_character_bounds_.size())
2433 *rect = ConvertRectToScreen(composition_character_bounds_[index]);
2437 bool RenderWidgetHostViewAura::HasCompositionText() const {
2438 return has_composition_text_;
2441 bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) const {
2442 range->set_start(selection_text_offset_);
2443 range->set_end(selection_text_offset_ + selection_text_.length());
2447 bool RenderWidgetHostViewAura::GetCompositionTextRange(
2448 gfx::Range* range) const {
2449 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
2454 bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) const {
2455 range->set_start(selection_range_.start());
2456 range->set_end(selection_range_.end());
2460 bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) {
2461 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
2466 bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) {
2467 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
2472 bool RenderWidgetHostViewAura::GetTextFromRange(
2473 const gfx::Range& range,
2474 base::string16* text) const {
2475 gfx::Range selection_text_range(selection_text_offset_,
2476 selection_text_offset_ + selection_text_.length());
2478 if (!selection_text_range.Contains(range)) {
2482 if (selection_text_range.EqualsIgnoringDirection(range)) {
2483 // Avoid calling substr whose performance is low.
2484 *text = selection_text_;
2486 *text = selection_text_.substr(
2487 range.GetMin() - selection_text_offset_,
2493 void RenderWidgetHostViewAura::OnInputMethodChanged() {
2497 if (GetInputMethod())
2498 host_->SetInputMethodActive(GetInputMethod()->IsActive());
2500 // TODO(suzhe): implement the newly added “locale” property of HTML DOM
2504 bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
2505 base::i18n::TextDirection direction) {
2508 host_->UpdateTextDirection(
2509 direction == base::i18n::RIGHT_TO_LEFT ?
2510 blink::WebTextDirectionRightToLeft :
2511 blink::WebTextDirectionLeftToRight);
2512 host_->NotifyTextDirection();
2516 void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
2517 size_t before, size_t after) {
2519 host_->ExtendSelectionAndDelete(before, after);
2522 void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
2523 gfx::Rect intersected_rect(
2524 gfx::IntersectRects(rect, window_->GetBoundsInScreen()));
2526 if (intersected_rect.IsEmpty())
2529 host_->ScrollFocusedEditableNodeIntoRect(
2530 ConvertRectFromScreen(intersected_rect));
2533 void RenderWidgetHostViewAura::OnCandidateWindowShown() {
2534 host_->CandidateWindowShown();
2537 void RenderWidgetHostViewAura::OnCandidateWindowUpdated() {
2538 host_->CandidateWindowUpdated();
2541 void RenderWidgetHostViewAura::OnCandidateWindowHidden() {
2542 host_->CandidateWindowHidden();
2545 ////////////////////////////////////////////////////////////////////////////////
2546 // RenderWidgetHostViewAura, gfx::DisplayObserver implementation:
2548 void RenderWidgetHostViewAura::OnDisplayBoundsChanged(
2549 const gfx::Display& display) {
2550 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
2551 if (display.id() == screen->GetDisplayNearestWindow(window_).id()) {
2552 UpdateScreenInfo(window_);
2553 current_cursor_.SetDisplayInfo(display);
2554 UpdateCursorIfOverSelf();
2558 void RenderWidgetHostViewAura::OnDisplayAdded(
2559 const gfx::Display& new_display) {
2562 void RenderWidgetHostViewAura::OnDisplayRemoved(
2563 const gfx::Display& old_display) {
2566 ////////////////////////////////////////////////////////////////////////////////
2567 // RenderWidgetHostViewAura, aura::WindowDelegate implementation:
2569 gfx::Size RenderWidgetHostViewAura::GetMinimumSize() const {
2573 gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const {
2577 void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
2578 const gfx::Rect& new_bounds) {
2579 base::AutoReset<bool> in_bounds_changed(&in_bounds_changed_, true);
2580 // We care about this whenever RenderWidgetHostViewAura is not owned by a
2581 // WebContentsViewAura since changes to the Window's bounds need to be
2582 // messaged to the renderer. WebContentsViewAura invokes SetSize() or
2583 // SetBounds() itself. No matter how we got here, any redundant calls are
2585 SetSize(new_bounds.size());
2588 gfx::NativeCursor RenderWidgetHostViewAura::GetCursor(const gfx::Point& point) {
2590 return ui::kCursorNone;
2591 return current_cursor_.GetNativeCursor();
2594 int RenderWidgetHostViewAura::GetNonClientComponent(
2595 const gfx::Point& point) const {
2599 bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
2600 aura::Window* child,
2601 const gfx::Point& location) {
2605 bool RenderWidgetHostViewAura::CanFocus() {
2606 return popup_type_ == blink::WebPopupTypeNone;
2609 void RenderWidgetHostViewAura::OnCaptureLost() {
2610 host_->LostCapture();
2611 if (touch_editing_client_)
2612 touch_editing_client_->EndTouchEditing(false);
2615 void RenderWidgetHostViewAura::OnPaint(gfx::Canvas* canvas) {
2616 bool has_backing_store = !!host_->GetBackingStore(false);
2617 if (has_backing_store) {
2618 paint_canvas_ = canvas;
2619 BackingStoreAura* backing_store = static_cast<BackingStoreAura*>(
2620 host_->GetBackingStore(true));
2621 paint_canvas_ = NULL;
2622 backing_store->SkiaShowRect(gfx::Point(), canvas);
2624 ui::Compositor* compositor = GetCompositor();
2626 for (size_t i = 0; i < software_latency_info_.size(); i++)
2627 compositor->SetLatencyInfo(software_latency_info_[i]);
2629 software_latency_info_.clear();
2631 // For non-opaque windows, we don't draw anything, since we depend on the
2632 // canvas coming from the compositor to already be initialized as
2634 if (window_->layer()->fills_bounds_opaquely())
2635 canvas->DrawColor(SK_ColorWHITE);
2639 void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
2640 float device_scale_factor) {
2644 BackingStoreAura* backing_store = static_cast<BackingStoreAura*>(
2645 host_->GetBackingStore(false));
2646 if (backing_store) // NULL in hardware path.
2647 backing_store->ScaleFactorChanged(device_scale_factor);
2649 UpdateScreenInfo(window_);
2651 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
2652 GetDisplayNearestWindow(window_);
2653 DCHECK_EQ(device_scale_factor, display.device_scale_factor());
2654 current_cursor_.SetDisplayInfo(display);
2657 void RenderWidgetHostViewAura::OnWindowDestroying() {
2660 // If the tab was hidden and it's closed, host_->is_hidden would have been
2661 // reset to false in RenderWidgetHostImpl::RendererExited.
2662 if (!window_->GetRootWindow() || host_->is_hidden()) {
2663 parent = ui::GetHiddenWindow();
2665 parent = window_->GetDispatcher()->host()->GetAcceleratedWidget();
2667 LPARAM lparam = reinterpret_cast<LPARAM>(this);
2668 EnumChildWindows(parent, WindowDestroyingCallback, lparam);
2671 // Make sure that the input method no longer references to this object before
2672 // this object is removed from the root window (i.e. this object loses access
2673 // to the input method).
2674 ui::InputMethod* input_method = GetInputMethod();
2676 input_method->DetachTextInputClient(this);
2679 void RenderWidgetHostViewAura::OnWindowDestroyed() {
2680 host_->ViewDestroyed();
2684 void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible) {
2687 bool RenderWidgetHostViewAura::HasHitTestMask() const {
2691 void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
2694 void RenderWidgetHostViewAura::DidRecreateLayer(ui::Layer *old_layer,
2695 ui::Layer *new_layer) {
2696 float mailbox_scale_factor;
2697 cc::TextureMailbox old_mailbox =
2698 old_layer->GetTextureMailbox(&mailbox_scale_factor);
2699 scoped_refptr<ui::Texture> old_texture = old_layer->external_texture();
2700 // The new_layer is the one that will be used by our Window, so that's the one
2701 // that should keep our texture. old_layer will be returned to the
2702 // RecreateLayer caller, and should have a copy.
2703 if (old_texture.get()) {
2704 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
2705 GLHelper* gl_helper = factory->GetGLHelper();
2706 scoped_refptr<ui::Texture> new_texture;
2707 if (host_->is_accelerated_compositing_active() &&
2708 gl_helper && current_surface_.get()) {
2710 gl_helper->CopyTexture(current_surface_->PrepareTexture(),
2711 current_surface_->size());
2713 new_texture = factory->CreateOwnedTexture(
2714 current_surface_->size(),
2715 current_surface_->device_scale_factor(), texture_id);
2718 if (new_texture.get())
2719 old_layer->SetExternalTexture(new_texture.get());
2721 old_layer->SetShowPaintedContent();
2722 new_layer->SetExternalTexture(old_texture.get());
2723 } else if (old_mailbox.IsSharedMemory()) {
2724 base::SharedMemory* old_buffer = old_mailbox.shared_memory();
2725 const size_t size = old_mailbox.shared_memory_size_in_bytes();
2727 scoped_ptr<base::SharedMemory> new_buffer(new base::SharedMemory);
2728 new_buffer->CreateAndMapAnonymous(size);
2730 if (old_buffer->memory() && new_buffer->memory()) {
2731 memcpy(new_buffer->memory(), old_buffer->memory(), size);
2732 base::SharedMemory* new_buffer_raw_ptr = new_buffer.get();
2733 scoped_ptr<cc::SingleReleaseCallback> callback =
2734 cc::SingleReleaseCallback::Create(base::Bind(MailboxReleaseCallback,
2735 Passed(&new_buffer)));
2736 cc::TextureMailbox new_mailbox(new_buffer_raw_ptr,
2737 old_mailbox.shared_memory_size());
2738 new_layer->SetTextureMailbox(new_mailbox,
2740 mailbox_scale_factor);
2742 } else if (frame_provider_.get()) {
2743 new_layer->SetShowDelegatedContent(frame_provider_.get(),
2744 current_frame_size_);
2748 ////////////////////////////////////////////////////////////////////////////////
2749 // RenderWidgetHostViewAura, ui::EventHandler implementation:
2751 void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
2752 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent");
2753 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2756 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
2757 popup_child_host_view_->OnKeyEvent(event);
2758 if (event->handled())
2762 // We need to handle the Escape key for Pepper Flash.
2763 if (is_fullscreen_ && event->key_code() == ui::VKEY_ESCAPE) {
2764 // Focus the window we were created from.
2765 if (host_tracker_.get() && !host_tracker_->windows().empty()) {
2766 aura::Window* host = *(host_tracker_->windows().begin());
2767 aura::client::FocusClient* client = aura::client::GetFocusClient(host);
2769 // Calling host->Focus() may delete |this|. We create a local observer
2770 // for that. In that case we exit without further access to any members.
2771 aura::WindowTracker tracker;
2772 aura::Window* window = window_;
2773 tracker.Add(window);
2775 if (!tracker.Contains(window)) {
2776 event->SetHandled();
2781 if (!in_shutdown_) {
2782 in_shutdown_ = true;
2786 if (event->key_code() == ui::VKEY_RETURN) {
2787 // Do not forward return key release events if no press event was handled.
2788 if (event->type() == ui::ET_KEY_RELEASED && !accept_return_character_)
2790 // Accept return key character events between press and release events.
2791 accept_return_character_ = event->type() == ui::ET_KEY_PRESSED;
2794 // We don't have to communicate with an input method here.
2795 if (!event->HasNativeEvent()) {
2796 NativeWebKeyboardEvent webkit_event(
2799 event->is_char() ? event->GetCharacter() : event->key_code(),
2801 ui::EventTimeForNow().InSecondsF());
2802 host_->ForwardKeyboardEvent(webkit_event);
2804 NativeWebKeyboardEvent webkit_event(event);
2805 host_->ForwardKeyboardEvent(webkit_event);
2808 event->SetHandled();
2811 void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
2812 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
2814 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2817 if (mouse_locked_) {
2818 aura::client::CursorClient* cursor_client =
2819 aura::client::GetCursorClient(window_->GetRootWindow());
2820 DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
2822 if (event->type() == ui::ET_MOUSEWHEEL) {
2823 blink::WebMouseWheelEvent mouse_wheel_event =
2824 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
2825 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
2826 host_->ForwardWheelEvent(mouse_wheel_event);
2830 gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
2832 // If we receive non client mouse messages while we are in the locked state
2833 // it probably means that the mouse left the borders of our window and
2834 // needs to be moved back to the center.
2835 if (event->flags() & ui::EF_IS_NON_CLIENT) {
2836 synthetic_move_sent_ = true;
2837 window_->MoveCursorTo(center);
2841 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
2843 bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED ||
2844 event->type() == ui::ET_MOUSE_DRAGGED) &&
2845 mouse_event.x == center.x() && mouse_event.y == center.y();
2847 ModifyEventMovementAndCoords(&mouse_event);
2849 bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
2850 if (should_not_forward) {
2851 synthetic_move_sent_ = false;
2853 // Check if the mouse has reached the border and needs to be centered.
2854 if (ShouldMoveToCenter()) {
2855 synthetic_move_sent_ = true;
2856 window_->MoveCursorTo(center);
2858 // Forward event to renderer.
2859 if (CanRendererHandleEvent(event) &&
2860 !(event->flags() & ui::EF_FROM_TOUCH)) {
2861 host_->ForwardMouseEvent(mouse_event);
2862 // Ensure that we get keyboard focus on mouse down as a plugin window
2863 // may have grabbed keyboard focus.
2864 if (event->type() == ui::ET_MOUSE_PRESSED)
2871 // As the overscroll is handled during scroll events from the trackpad, the
2872 // RWHVA window is transformed by the overscroll controller. This transform
2873 // triggers a synthetic mouse-move event to be generated (by the aura
2874 // RootWindow). But this event interferes with the overscroll gesture. So,
2875 // ignore such synthetic mouse-move events if an overscroll gesture is in
2877 if (host_->overscroll_controller() &&
2878 host_->overscroll_controller()->overscroll_mode() != OVERSCROLL_NONE &&
2879 event->flags() & ui::EF_IS_SYNTHESIZED &&
2880 (event->type() == ui::ET_MOUSE_ENTERED ||
2881 event->type() == ui::ET_MOUSE_EXITED ||
2882 event->type() == ui::ET_MOUSE_MOVED)) {
2883 event->StopPropagation();
2887 if (event->type() == ui::ET_MOUSEWHEEL) {
2889 // We get mouse wheel/scroll messages even if we are not in the foreground.
2890 // So here we check if we have any owned popup windows in the foreground and
2892 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
2894 HWND parent = dispatcher->host()->GetAcceleratedWidget();
2895 HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
2896 EnumThreadWindows(GetCurrentThreadId(),
2898 reinterpret_cast<LPARAM>(toplevel_hwnd));
2901 blink::WebMouseWheelEvent mouse_wheel_event =
2902 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
2903 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
2904 host_->ForwardWheelEvent(mouse_wheel_event);
2905 } else if (CanRendererHandleEvent(event) &&
2906 !(event->flags() & ui::EF_FROM_TOUCH)) {
2907 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
2908 ModifyEventMovementAndCoords(&mouse_event);
2909 host_->ForwardMouseEvent(mouse_event);
2910 // Ensure that we get keyboard focus on mouse down as a plugin window may
2911 // have grabbed keyboard focus.
2912 if (event->type() == ui::ET_MOUSE_PRESSED)
2916 switch (event->type()) {
2917 case ui::ET_MOUSE_PRESSED:
2918 window_->SetCapture();
2919 // Confirm existing composition text on mouse click events, to make sure
2920 // the input caret won't be moved with an ongoing composition text.
2921 FinishImeCompositionSession();
2923 case ui::ET_MOUSE_RELEASED:
2924 window_->ReleaseCapture();
2930 // Needed to propagate mouse event to |window_->parent()->delegate()|, but
2931 // note that it might be something other than a WebContentsViewAura instance.
2932 // TODO(pkotwicz): Find a better way of doing this.
2933 // In fullscreen mode which is typically used by flash, don't forward
2934 // the mouse events to the parent. The renderer and the plugin process
2935 // handle these events.
2936 if (!is_fullscreen_ && window_->parent()->delegate() &&
2937 !(event->flags() & ui::EF_FROM_TOUCH)) {
2938 event->ConvertLocationToTarget(window_, window_->parent());
2939 window_->parent()->delegate()->OnMouseEvent(event);
2942 if (!IsXButtonUpEvent(event))
2943 event->SetHandled();
2946 void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
2947 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
2948 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2951 if (event->type() == ui::ET_SCROLL) {
2952 #if !defined(OS_WIN)
2954 // Investigate if this is true for Windows 8 Metro ASH as well.
2955 if (event->finger_count() != 2)
2958 blink::WebGestureEvent gesture_event =
2959 MakeWebGestureEventFlingCancel();
2960 host_->ForwardGestureEvent(gesture_event);
2961 blink::WebMouseWheelEvent mouse_wheel_event =
2962 MakeWebMouseWheelEvent(event);
2963 host_->ForwardWheelEvent(mouse_wheel_event);
2964 RecordAction(base::UserMetricsAction("TrackpadScroll"));
2965 } else if (event->type() == ui::ET_SCROLL_FLING_START ||
2966 event->type() == ui::ET_SCROLL_FLING_CANCEL) {
2967 blink::WebGestureEvent gesture_event =
2968 MakeWebGestureEvent(event);
2969 host_->ForwardGestureEvent(gesture_event);
2970 if (event->type() == ui::ET_SCROLL_FLING_START)
2971 RecordAction(base::UserMetricsAction("TrackpadScrollFling"));
2974 event->SetHandled();
2977 void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
2978 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent");
2979 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2982 // Update the touch event first.
2983 blink::WebTouchPoint* point = UpdateWebTouchEventFromUIEvent(*event,
2986 // Forward the touch event only if a touch point was updated, and there's a
2987 // touch-event handler in the page, and no other touch-event is in the queue.
2988 // It is important to always consume the event if there is a touch-event
2989 // handler in the page, or some touch-event is already in the queue, even if
2990 // no point has been updated, to make sure that this event does not get
2991 // processed by the gesture recognizer before the events in the queue.
2992 if (host_->ShouldForwardTouchEvent())
2993 event->StopPropagation();
2996 if (host_->ShouldForwardTouchEvent())
2997 host_->ForwardTouchEventWithLatencyInfo(touch_event_, *event->latency());
2998 UpdateWebTouchEventAfterDispatch(&touch_event_, point);
3002 void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
3003 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent");
3004 if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN ||
3005 event->type() == ui::ET_GESTURE_PINCH_UPDATE ||
3006 event->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) {
3007 event->SetHandled();
3011 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
3014 RenderViewHostDelegate* delegate = NULL;
3015 if (popup_type_ == blink::WebPopupTypeNone && !is_fullscreen_)
3016 delegate = RenderViewHost::From(host_)->GetDelegate();
3018 if (delegate && event->type() == ui::ET_GESTURE_BEGIN &&
3019 event->details().touch_points() == 1) {
3020 delegate->HandleGestureBegin();
3023 blink::WebGestureEvent gesture = MakeWebGestureEvent(event);
3024 if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
3025 // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
3026 // event to stop any in-progress flings.
3027 blink::WebGestureEvent fling_cancel = gesture;
3028 fling_cancel.type = blink::WebInputEvent::GestureFlingCancel;
3029 fling_cancel.sourceDevice = blink::WebGestureEvent::Touchscreen;
3030 host_->ForwardGestureEvent(fling_cancel);
3033 if (gesture.type != blink::WebInputEvent::Undefined) {
3034 host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
3036 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
3037 event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
3038 event->type() == ui::ET_GESTURE_SCROLL_END) {
3039 RecordAction(base::UserMetricsAction("TouchscreenScroll"));
3040 } else if (event->type() == ui::ET_SCROLL_FLING_START) {
3041 RecordAction(base::UserMetricsAction("TouchscreenScrollFling"));
3045 if (delegate && event->type() == ui::ET_GESTURE_END &&
3046 event->details().touch_points() == 1) {
3047 delegate->HandleGestureEnd();
3050 // If a gesture is not processed by the webpage, then WebKit processes it
3051 // (e.g. generates synthetic mouse events).
3052 event->SetHandled();
3055 ////////////////////////////////////////////////////////////////////////////////
3056 // RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation:
3058 bool RenderWidgetHostViewAura::ShouldActivate() const {
3059 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
3062 const ui::Event* event = dispatcher->current_event();
3065 return is_fullscreen_;
3068 ////////////////////////////////////////////////////////////////////////////////
3069 // RenderWidgetHostViewAura,
3070 // aura::client::ActivationChangeObserver implementation:
3072 void RenderWidgetHostViewAura::OnWindowActivated(aura::Window* gained_active,
3073 aura::Window* lost_active) {
3074 DCHECK(window_ == gained_active || window_ == lost_active);
3075 if (window_ == gained_active) {
3076 const ui::Event* event = window_->GetDispatcher()->current_event();
3077 if (event && PointerEventActivates(*event))
3078 host_->OnPointerEventActivate();
3082 ////////////////////////////////////////////////////////////////////////////////
3083 // RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation:
3085 void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible) {
3086 NotifyRendererOfCursorVisibilityState(is_visible);
3089 ////////////////////////////////////////////////////////////////////////////////
3090 // RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation:
3092 void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
3093 aura::Window* lost_focus) {
3094 DCHECK(window_ == gained_focus || window_ == lost_focus);
3095 if (window_ == gained_focus) {
3096 // We need to honor input bypass if the associated tab is does not want
3097 // input. This gives the current focused window a chance to be the text
3098 // input client and handle events.
3099 if (host_->ignore_input_events())
3103 host_->SetActive(true);
3105 ui::InputMethod* input_method = GetInputMethod();
3107 // Ask the system-wide IME to send all TextInputClient messages to |this|
3109 input_method->SetFocusedTextInputClient(this);
3110 host_->SetInputMethodActive(input_method->IsActive());
3112 // Often the application can set focus to the view in response to a key
3113 // down. However the following char event shouldn't be sent to the web
3115 host_->SuppressNextCharEvents();
3117 host_->SetInputMethodActive(false);
3119 } else if (window_ == lost_focus) {
3120 host_->SetActive(false);
3123 DetachFromInputMethod();
3124 host_->SetInputMethodActive(false);
3126 if (touch_editing_client_)
3127 touch_editing_client_->EndTouchEditing(false);
3129 // If we lose the focus while fullscreen, close the window; Pepper Flash
3130 // won't do it for us (unlike NPAPI Flash). However, we do not close the
3131 // window if we lose the focus to a window on another display.
3132 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
3133 bool focusing_other_display =
3134 gained_focus && screen->GetNumDisplays() > 1 &&
3135 (screen->GetDisplayNearestWindow(window_).id() !=
3136 screen->GetDisplayNearestWindow(gained_focus).id());
3137 if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) {
3139 // On Windows, if we are switching to a non Aura Window on a different
3140 // screen we should not close the fullscreen window.
3141 if (!gained_focus) {
3143 ::GetCursorPos(&point);
3144 if (screen->GetDisplayNearestWindow(window_).id() !=
3145 screen->GetDisplayNearestPoint(gfx::Point(point)).id())
3149 in_shutdown_ = true;
3155 ////////////////////////////////////////////////////////////////////////////////
3156 // RenderWidgetHostViewAura, aura::RootWindowObserver implementation:
3158 void RenderWidgetHostViewAura::OnWindowTreeHostMoved(
3159 const aura::RootWindow* root,
3160 const gfx::Point& new_origin) {
3161 TRACE_EVENT1("ui", "RenderWidgetHostViewAura::OnWindowTreeHostMoved",
3162 "new_origin", new_origin.ToString());
3164 UpdateScreenInfo(window_);
3167 ////////////////////////////////////////////////////////////////////////////////
3168 // RenderWidgetHostViewAura, SoftwareFrameManagerClient implementation:
3170 void RenderWidgetHostViewAura::SoftwareFrameWasFreed(
3171 uint32 output_surface_id, unsigned frame_id) {
3172 ReleaseSoftwareFrame(output_surface_id, frame_id);
3175 void RenderWidgetHostViewAura::ReleaseReferencesToSoftwareFrame() {
3176 ui::Compositor* compositor = GetCompositor();
3178 AddOnCommitCallbackAndDisableLocks(base::Bind(
3179 &RenderWidgetHostViewAura::SendReclaimSoftwareFrames, AsWeakPtr()));
3181 UpdateExternalTexture();
3184 ////////////////////////////////////////////////////////////////////////////////
3185 // RenderWidgetHostViewAura, ui::CompositorObserver implementation:
3187 void RenderWidgetHostViewAura::OnCompositingDidCommit(
3188 ui::Compositor* compositor) {
3189 if (can_lock_compositor_ == NO_PENDING_COMMIT) {
3190 can_lock_compositor_ = YES;
3191 if (resize_lock_.get() && resize_lock_->GrabDeferredLock())
3192 can_lock_compositor_ = YES_DID_LOCK;
3194 RunOnCommitCallbacks();
3195 if (resize_lock_ && resize_lock_->expected_size() == current_frame_size_) {
3196 resize_lock_.reset();
3197 host_->WasResized();
3198 // We may have had a resize while we had the lock (e.g. if the lock expired,
3199 // or if the UI still gave us some resizes), so make sure we grab a new lock
3201 MaybeCreateResizeLock();
3205 void RenderWidgetHostViewAura::OnCompositingStarted(
3206 ui::Compositor* compositor, base::TimeTicks start_time) {
3207 last_draw_ended_ = start_time;
3210 void RenderWidgetHostViewAura::OnCompositingEnded(
3211 ui::Compositor* compositor) {
3214 void RenderWidgetHostViewAura::OnCompositingAborted(
3215 ui::Compositor* compositor) {
3218 void RenderWidgetHostViewAura::OnCompositingLockStateChanged(
3219 ui::Compositor* compositor) {
3220 // A compositor lock that is part of a resize lock timed out. We
3221 // should display a renderer frame.
3222 if (!compositor->IsLocked() && can_lock_compositor_ == YES_DID_LOCK) {
3223 can_lock_compositor_ = NO_PENDING_RENDERER_FRAME;
3227 void RenderWidgetHostViewAura::OnUpdateVSyncParameters(
3228 base::TimeTicks timebase,
3229 base::TimeDelta interval) {
3231 if (IsDeadlineSchedulingEnabled()) {
3232 // The deadline scheduler has logic to stagger the draws of the
3233 // Renderer and Browser built-in, so send it an accurate timebase.
3234 host_->UpdateVSyncParameters(timebase, interval);
3235 } else if (!last_draw_ended_.is_null()) {
3236 // For the non-deadline scheduler, we send the Renderer an offset
3237 // vsync timebase to avoid its draws racing the Browser's draws.
3238 host_->UpdateVSyncParameters(last_draw_ended_, interval);
3243 ////////////////////////////////////////////////////////////////////////////////
3244 // RenderWidgetHostViewAura, BrowserAccessibilityDelegate implementation:
3246 void RenderWidgetHostViewAura::SetAccessibilityFocus(int acc_obj_id) {
3250 host_->AccessibilitySetFocus(acc_obj_id);
3253 void RenderWidgetHostViewAura::AccessibilityDoDefaultAction(int acc_obj_id) {
3257 host_->AccessibilityDoDefaultAction(acc_obj_id);
3260 void RenderWidgetHostViewAura::AccessibilityScrollToMakeVisible(
3261 int acc_obj_id, gfx::Rect subfocus) {
3265 host_->AccessibilityScrollToMakeVisible(acc_obj_id, subfocus);
3268 void RenderWidgetHostViewAura::AccessibilityScrollToPoint(
3269 int acc_obj_id, gfx::Point point) {
3273 host_->AccessibilityScrollToPoint(acc_obj_id, point);
3276 void RenderWidgetHostViewAura::AccessibilitySetTextSelection(
3277 int acc_obj_id, int start_offset, int end_offset) {
3281 host_->AccessibilitySetTextSelection(
3282 acc_obj_id, start_offset, end_offset);
3285 gfx::Point RenderWidgetHostViewAura::GetLastTouchEventLocation() const {
3286 // Only needed for Win 8 non-aura.
3287 return gfx::Point();
3290 void RenderWidgetHostViewAura::FatalAccessibilityTreeError() {
3291 host_->FatalAccessibilityTreeError();
3292 SetBrowserAccessibilityManager(NULL);
3295 ////////////////////////////////////////////////////////////////////////////////
3296 // RenderWidgetHostViewAura, ImageTransportFactoryObserver implementation:
3298 void RenderWidgetHostViewAura::OnLostResources() {
3299 current_surface_ = NULL;
3300 UpdateExternalTexture();
3302 idle_frame_subscriber_textures_.clear();
3303 yuv_readback_pipeline_.reset();
3305 // Make sure all ImageTransportClients are deleted now that the context those
3306 // are using is becoming invalid. This sends pending ACKs and needs to happen
3307 // after calling UpdateExternalTexture() which syncs with the impl thread.
3308 RunOnCommitCallbacks();
3309 host_->ScheduleComposite();
3312 ////////////////////////////////////////////////////////////////////////////////
3313 // RenderWidgetHostViewAura, private:
3315 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
3316 if (touch_editing_client_)
3317 touch_editing_client_->OnViewDestroyed();
3319 ImageTransportFactory::GetInstance()->RemoveObserver(this);
3321 window_observer_.reset();
3322 if (window_->GetDispatcher())
3323 window_->GetDispatcher()->RemoveRootWindowObserver(this);
3325 if (popup_parent_host_view_) {
3326 DCHECK(popup_parent_host_view_->popup_child_host_view_ == NULL ||
3327 popup_parent_host_view_->popup_child_host_view_ == this);
3328 popup_parent_host_view_->popup_child_host_view_ = NULL;
3330 if (popup_child_host_view_) {
3331 DCHECK(popup_child_host_view_->popup_parent_host_view_ == NULL ||
3332 popup_child_host_view_->popup_parent_host_view_ == this);
3333 popup_child_host_view_->popup_parent_host_view_ = NULL;
3335 event_filter_for_popup_exit_.reset();
3336 aura::client::SetTooltipText(window_, NULL);
3337 gfx::Screen::GetScreenFor(window_)->RemoveObserver(this);
3339 // This call is usually no-op since |this| object is already removed from the
3340 // Aura root window and we don't have a way to get an input method object
3341 // associated with the window, but just in case.
3342 DetachFromInputMethod();
3344 if (resource_collection_.get())
3345 resource_collection_->SetClient(NULL);
3347 // An OwnedMailbox should not refer to the GLHelper anymore once the RWHVA is
3348 // destroyed, as it may then outlive the GLHelper.
3349 for (std::set<OwnedMailbox*>::iterator it =
3350 active_frame_subscriber_textures_.begin();
3351 it != active_frame_subscriber_textures_.end();
3355 active_frame_subscriber_textures_.clear();
3358 legacy_render_widget_host_HWND_.reset(NULL);
3361 DCHECK(!vsync_manager_);
3364 void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
3365 const gfx::Point screen_point =
3366 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
3367 aura::Window* root_window = window_->GetRootWindow();
3371 gfx::Point root_window_point = screen_point;
3372 aura::client::ScreenPositionClient* screen_position_client =
3373 aura::client::GetScreenPositionClient(root_window);
3374 if (screen_position_client) {
3375 screen_position_client->ConvertPointFromScreen(
3376 root_window, &root_window_point);
3379 if (root_window->GetEventHandlerForPoint(root_window_point) != window_)
3382 gfx::NativeCursor cursor = current_cursor_.GetNativeCursor();
3383 // Do not show loading cursor when the cursor is currently hidden.
3384 if (is_loading_ && cursor != ui::kCursorNone)
3385 cursor = ui::kCursorPointer;
3387 aura::client::CursorClient* cursor_client =
3388 aura::client::GetCursorClient(root_window);
3389 if (cursor_client) {
3390 cursor_client->SetCursor(cursor);
3394 ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
3395 aura::Window* root_window = window_->GetRootWindow();
3398 return root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
3401 bool RenderWidgetHostViewAura::NeedsInputGrab() {
3402 return popup_type_ == blink::WebPopupTypeSelect;
3405 void RenderWidgetHostViewAura::FinishImeCompositionSession() {
3406 if (!has_composition_text_)
3409 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
3412 ImeCancelComposition();
3415 void RenderWidgetHostViewAura::ModifyEventMovementAndCoords(
3416 blink::WebMouseEvent* event) {
3417 // If the mouse has just entered, we must report zero movementX/Y. Hence we
3418 // reset any global_mouse_position set previously.
3419 if (event->type == blink::WebInputEvent::MouseEnter ||
3420 event->type == blink::WebInputEvent::MouseLeave)
3421 global_mouse_position_.SetPoint(event->globalX, event->globalY);
3423 // Movement is computed by taking the difference of the new cursor position
3424 // and the previous. Under mouse lock the cursor will be warped back to the
3425 // center so that we are not limited by clipping boundaries.
3426 // We do not measure movement as the delta from cursor to center because
3427 // we may receive more mouse movement events before our warp has taken
3429 event->movementX = event->globalX - global_mouse_position_.x();
3430 event->movementY = event->globalY - global_mouse_position_.y();
3432 global_mouse_position_.SetPoint(event->globalX, event->globalY);
3434 // Under mouse lock, coordinates of mouse are locked to what they were when
3435 // mouse lock was entered.
3436 if (mouse_locked_) {
3437 event->x = unlocked_mouse_position_.x();
3438 event->y = unlocked_mouse_position_.y();
3439 event->windowX = unlocked_mouse_position_.x();
3440 event->windowY = unlocked_mouse_position_.y();
3441 event->globalX = unlocked_global_mouse_position_.x();
3442 event->globalY = unlocked_global_mouse_position_.y();
3444 unlocked_mouse_position_.SetPoint(event->windowX, event->windowY);
3445 unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY);
3449 void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
3451 if (host_->is_hidden() ||
3452 (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) ||
3453 (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible))
3456 cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE;
3457 host_->SendCursorVisibilityState(is_visible);
3460 void RenderWidgetHostViewAura::SchedulePaintIfNotInClip(
3461 const gfx::Rect& rect,
3462 const gfx::Rect& clip) {
3463 if (!clip.IsEmpty()) {
3464 gfx::Rect to_paint = gfx::SubtractRects(rect, clip);
3465 if (!to_paint.IsEmpty())
3466 window_->SchedulePaintInRect(to_paint);
3468 window_->SchedulePaintInRect(rect);
3472 bool RenderWidgetHostViewAura::ShouldMoveToCenter() {
3473 gfx::Rect rect = window_->bounds();
3474 rect = ConvertRectToScreen(rect);
3475 int border_x = rect.width() * kMouseLockBorderPercentage / 100;
3476 int border_y = rect.height() * kMouseLockBorderPercentage / 100;
3478 return global_mouse_position_.x() < rect.x() + border_x ||
3479 global_mouse_position_.x() > rect.right() - border_x ||
3480 global_mouse_position_.y() < rect.y() + border_y ||
3481 global_mouse_position_.y() > rect.bottom() - border_y;
3484 void RenderWidgetHostViewAura::RunOnCommitCallbacks() {
3485 for (std::vector<base::Closure>::const_iterator
3486 it = on_compositing_did_commit_callbacks_.begin();
3487 it != on_compositing_did_commit_callbacks_.end(); ++it) {
3490 on_compositing_did_commit_callbacks_.clear();
3493 void RenderWidgetHostViewAura::AddOnCommitCallbackAndDisableLocks(
3494 const base::Closure& callback) {
3495 ui::Compositor* compositor = GetCompositor();
3498 if (!compositor->HasObserver(this))
3499 compositor->AddObserver(this);
3501 can_lock_compositor_ = NO_PENDING_COMMIT;
3502 on_compositing_did_commit_callbacks_.push_back(callback);
3505 void RenderWidgetHostViewAura::AddedToRootWindow() {
3506 window_->GetDispatcher()->AddRootWindowObserver(this);
3507 UpdateScreenInfo(window_);
3509 aura::client::CursorClient* cursor_client =
3510 aura::client::GetCursorClient(window_->GetRootWindow());
3511 if (cursor_client) {
3512 cursor_client->AddObserver(this);
3513 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
3515 if (current_surface_.get())
3516 UpdateExternalTexture();
3518 ui::InputMethod* input_method = GetInputMethod();
3520 input_method->SetFocusedTextInputClient(this);
3524 // The parent may have changed here. Ensure that the legacy window is
3525 // reparented accordingly.
3526 if (legacy_render_widget_host_HWND_)
3527 legacy_render_widget_host_HWND_->UpdateParent(
3528 reinterpret_cast<HWND>(GetNativeViewId()));
3531 ui::Compositor* compositor = GetCompositor();
3533 DCHECK(!vsync_manager_);
3534 vsync_manager_ = compositor->vsync_manager();
3535 vsync_manager_->AddObserver(this);
3539 void RenderWidgetHostViewAura::RemovingFromRootWindow() {
3540 aura::client::CursorClient* cursor_client =
3541 aura::client::GetCursorClient(window_->GetRootWindow());
3543 cursor_client->RemoveObserver(this);
3545 DetachFromInputMethod();
3547 window_->GetDispatcher()->RemoveRootWindowObserver(this);
3548 ui::Compositor* compositor = GetCompositor();
3549 if (current_surface_.get()) {
3550 // We can't get notification for commits after this point, which would
3551 // guarantee that the compositor isn't using an old texture any more, so
3552 // instead we force the layer to stop using any external resources which
3553 // synchronizes with the compositor thread, and makes it safe to run the
3555 window_->layer()->SetShowPaintedContent();
3557 RunOnCommitCallbacks();
3558 resize_lock_.reset();
3559 host_->WasResized();
3561 if (compositor && compositor->HasObserver(this))
3562 compositor->RemoveObserver(this);
3565 // Update the legacy window's parent temporarily to the desktop window. It
3566 // will eventually get reparented to the right root.
3567 if (legacy_render_widget_host_HWND_)
3568 legacy_render_widget_host_HWND_->UpdateParent(::GetDesktopWindow());
3571 if (vsync_manager_) {
3572 vsync_manager_->RemoveObserver(this);
3573 vsync_manager_ = NULL;
3577 ui::Compositor* RenderWidgetHostViewAura::GetCompositor() const {
3578 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
3579 return dispatcher ? dispatcher->host()->compositor() : NULL;
3582 void RenderWidgetHostViewAura::DetachFromInputMethod() {
3583 ui::InputMethod* input_method = GetInputMethod();
3584 if (input_method && input_method->GetTextInputClient() == this)
3585 input_method->SetFocusedTextInputClient(NULL);
3588 void RenderWidgetHostViewAura::LockResources() {
3589 DCHECK(frame_provider_);
3590 delegated_frame_evictor_->LockFrame();
3593 void RenderWidgetHostViewAura::UnlockResources() {
3594 DCHECK(frame_provider_);
3595 delegated_frame_evictor_->UnlockFrame();
3598 ////////////////////////////////////////////////////////////////////////////////
3599 // RenderWidgetHostView, public:
3602 RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
3603 RenderWidgetHost* widget) {
3604 return new RenderWidgetHostViewAura(widget);
3608 void RenderWidgetHostViewPort::GetDefaultScreenInfo(WebScreenInfo* results) {
3609 GetScreenInfoForWindow(results, NULL);
3612 } // namespace content