Ignore non-active fullscreen windows for shelf state.
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_aura.cc
blob2be8603d2725c4b7b7ab1458611152b5ce0e01d6
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"
9 #include "base/bind.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/aura/compositor_resize_lock.h"
26 #include "content/browser/gpu/compositor_util.h"
27 #include "content/browser/renderer_host/backing_store_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/browser_thread.h"
41 #include "content/public/browser/content_browser_client.h"
42 #include "content/public/browser/render_process_host.h"
43 #include "content/public/browser/render_view_host.h"
44 #include "content/public/browser/user_metrics.h"
45 #include "content/public/common/content_switches.h"
46 #include "media/base/video_util.h"
47 #include "skia/ext/image_operations.h"
48 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
49 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
50 #include "third_party/WebKit/public/web/WebInputEvent.h"
51 #include "ui/aura/client/activation_client.h"
52 #include "ui/aura/client/aura_constants.h"
53 #include "ui/aura/client/cursor_client.h"
54 #include "ui/aura/client/cursor_client_observer.h"
55 #include "ui/aura/client/focus_client.h"
56 #include "ui/aura/client/screen_position_client.h"
57 #include "ui/aura/client/tooltip_client.h"
58 #include "ui/aura/client/window_tree_client.h"
59 #include "ui/aura/client/window_types.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/layer.h"
70 #include "ui/events/event.h"
71 #include "ui/events/event_utils.h"
72 #include "ui/events/gestures/gesture_recognizer.h"
73 #include "ui/gfx/canvas.h"
74 #include "ui/gfx/display.h"
75 #include "ui/gfx/rect_conversions.h"
76 #include "ui/gfx/screen.h"
77 #include "ui/gfx/size_conversions.h"
78 #include "ui/gfx/skia_util.h"
80 #if defined(OS_WIN)
81 #include "base/win/windows_version.h"
82 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
83 #include "content/browser/accessibility/browser_accessibility_win.h"
84 #include "content/common/plugin_constants_win.h"
85 #include "ui/base/win/hidden_window.h"
86 #include "ui/gfx/gdi_util.h"
87 #include "ui/gfx/win/dpi.h"
88 #endif
90 using gfx::RectToSkIRect;
91 using gfx::SkIRectToRect;
93 using blink::WebScreenInfo;
94 using blink::WebTouchEvent;
96 namespace content {
98 namespace {
100 void MailboxReleaseCallback(scoped_ptr<base::SharedMemory> shared_memory,
101 unsigned sync_point, bool lost_resource) {
102 // NOTE: shared_memory will get released when we go out of scope.
105 // In mouse lock mode, we need to prevent the (invisible) cursor from hitting
106 // the border of the view, in order to get valid movement information. However,
107 // forcing the cursor back to the center of the view after each mouse move
108 // doesn't work well. It reduces the frequency of useful mouse move messages
109 // significantly. Therefore, we move the cursor to the center of the view only
110 // if it approaches the border. |kMouseLockBorderPercentage| specifies the width
111 // of the border area, in percentage of the corresponding dimension.
112 const int kMouseLockBorderPercentage = 15;
114 // When accelerated compositing is enabled and a widget resize is pending,
115 // we delay further resizes of the UI. The following constant is the maximum
116 // length of time that we should delay further UI resizes while waiting for a
117 // resized frame from a renderer.
118 const int kResizeLockTimeoutMs = 67;
120 #if defined(OS_WIN)
121 // Used to associate a plugin HWND with its RenderWidgetHostViewAura instance.
122 const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner";
124 BOOL CALLBACK WindowDestroyingCallback(HWND window, LPARAM param) {
125 RenderWidgetHostViewAura* widget =
126 reinterpret_cast<RenderWidgetHostViewAura*>(param);
127 if (GetProp(window, kWidgetOwnerProperty) == widget) {
128 // Properties set on HWNDs must be removed to avoid leaks.
129 RemoveProp(window, kWidgetOwnerProperty);
130 RenderWidgetHostViewBase::DetachPluginWindowsCallback(window);
132 return TRUE;
135 BOOL CALLBACK HideWindowsCallback(HWND window, LPARAM param) {
136 RenderWidgetHostViewAura* widget =
137 reinterpret_cast<RenderWidgetHostViewAura*>(param);
138 if (GetProp(window, kWidgetOwnerProperty) == widget)
139 SetParent(window, ui::GetHiddenWindow());
140 return TRUE;
143 BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) {
144 RenderWidgetHostViewAura* widget =
145 reinterpret_cast<RenderWidgetHostViewAura*>(param);
147 if (GetProp(window, kWidgetOwnerProperty) == widget) {
148 HWND parent = widget->GetNativeView()->GetDispatcher()->host()->
149 GetAcceleratedWidget();
150 SetParent(window, parent);
152 return TRUE;
155 struct CutoutRectsParams {
156 RenderWidgetHostViewAura* widget;
157 std::vector<gfx::Rect> cutout_rects;
158 std::map<HWND, WebPluginGeometry>* geometry;
161 // Used to update the region for the windowed plugin to draw in. We start with
162 // the clip rect from the renderer, then remove the cutout rects from the
163 // renderer, and then remove the transient windows from the root window and the
164 // constrained windows from the parent window.
165 BOOL CALLBACK SetCutoutRectsCallback(HWND window, LPARAM param) {
166 CutoutRectsParams* params = reinterpret_cast<CutoutRectsParams*>(param);
168 if (GetProp(window, kWidgetOwnerProperty) == params->widget) {
169 // First calculate the offset of this plugin from the root window, since
170 // the cutouts are relative to the root window.
171 HWND parent = params->widget->GetNativeView()->GetDispatcher()->
172 host()->GetAcceleratedWidget();
173 POINT offset;
174 offset.x = offset.y = 0;
175 MapWindowPoints(window, parent, &offset, 1);
177 // Now get the cached clip rect and cutouts for this plugin window that came
178 // from the renderer.
179 std::map<HWND, WebPluginGeometry>::iterator i = params->geometry->begin();
180 while (i != params->geometry->end() &&
181 i->second.window != window &&
182 GetParent(i->second.window) != window) {
183 ++i;
186 if (i == params->geometry->end()) {
187 NOTREACHED();
188 return TRUE;
191 HRGN hrgn = CreateRectRgn(i->second.clip_rect.x(),
192 i->second.clip_rect.y(),
193 i->second.clip_rect.right(),
194 i->second.clip_rect.bottom());
195 // We start with the cutout rects that came from the renderer, then add the
196 // ones that came from transient and constrained windows.
197 std::vector<gfx::Rect> cutout_rects = i->second.cutout_rects;
198 for (size_t i = 0; i < params->cutout_rects.size(); ++i) {
199 gfx::Rect offset_cutout = params->cutout_rects[i];
200 offset_cutout.Offset(-offset.x, -offset.y);
201 cutout_rects.push_back(offset_cutout);
203 gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects);
204 SetWindowRgn(window, hrgn, TRUE);
206 return TRUE;
209 // A callback function for EnumThreadWindows to enumerate and dismiss
210 // any owned popup windows.
211 BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
212 const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);
214 if (::IsWindowVisible(window)) {
215 const HWND owner = ::GetWindow(window, GW_OWNER);
216 if (toplevel_hwnd == owner) {
217 ::PostMessage(window, WM_CANCELMODE, 0, 0);
221 return TRUE;
223 #endif
225 void UpdateWebTouchEventAfterDispatch(blink::WebTouchEvent* event,
226 blink::WebTouchPoint* point) {
227 if (point->state != blink::WebTouchPoint::StateReleased &&
228 point->state != blink::WebTouchPoint::StateCancelled)
229 return;
230 --event->touchesLength;
231 for (unsigned i = point - event->touches;
232 i < event->touchesLength;
233 ++i) {
234 event->touches[i] = event->touches[i + 1];
238 bool CanRendererHandleEvent(const ui::MouseEvent* event) {
239 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
240 return false;
242 #if defined(OS_WIN)
243 // Renderer cannot handle WM_XBUTTON or NC events.
244 switch (event->native_event().message) {
245 case WM_XBUTTONDOWN:
246 case WM_XBUTTONUP:
247 case WM_XBUTTONDBLCLK:
248 case WM_NCMOUSELEAVE:
249 case WM_NCMOUSEMOVE:
250 case WM_NCXBUTTONDOWN:
251 case WM_NCXBUTTONUP:
252 case WM_NCXBUTTONDBLCLK:
253 return false;
254 default:
255 break;
257 #endif
258 return true;
261 // We don't mark these as handled so that they're sent back to the
262 // DefWindowProc so it can generate WM_APPCOMMAND as necessary.
263 bool IsXButtonUpEvent(const ui::MouseEvent* event) {
264 #if defined(OS_WIN)
265 switch (event->native_event().message) {
266 case WM_XBUTTONUP:
267 case WM_NCXBUTTONUP:
268 return true;
270 #endif
271 return false;
274 void GetScreenInfoForWindow(WebScreenInfo* results, aura::Window* window) {
275 const gfx::Display display = window ?
276 gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window) :
277 gfx::Screen::GetScreenFor(window)->GetPrimaryDisplay();
278 results->rect = display.bounds();
279 results->availableRect = display.work_area();
280 // TODO(derat|oshima): Don't hardcode this. Get this from display object.
281 results->depth = 24;
282 results->depthPerComponent = 8;
283 results->deviceScaleFactor = display.device_scale_factor();
286 bool ShouldSendPinchGesture() {
287 #if defined(OS_WIN)
288 if (base::win::GetVersion() >= base::win::VERSION_WIN8)
289 return true;
290 #endif
291 static bool pinch_allowed =
292 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableViewport) ||
293 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePinch);
294 return pinch_allowed;
297 bool PointerEventActivates(const ui::Event& event) {
298 if (event.type() == ui::ET_MOUSE_PRESSED)
299 return true;
301 if (event.type() == ui::ET_GESTURE_BEGIN) {
302 const ui::GestureEvent& gesture =
303 static_cast<const ui::GestureEvent&>(event);
304 return gesture.details().touch_points() == 1;
307 return false;
310 // Swap ack for the renderer when kCompositeToMailbox is enabled.
311 void SendCompositorFrameAck(
312 int32 route_id,
313 uint32 output_surface_id,
314 int renderer_host_id,
315 const gpu::Mailbox& received_mailbox,
316 const gfx::Size& received_size,
317 bool skip_frame,
318 const scoped_refptr<ui::Texture>& texture_to_produce) {
319 cc::CompositorFrameAck ack;
320 ack.gl_frame_data.reset(new cc::GLFrameData());
321 DCHECK(!texture_to_produce.get() || !skip_frame);
322 if (texture_to_produce.get()) {
323 std::string mailbox_name = texture_to_produce->Produce();
324 std::copy(mailbox_name.data(),
325 mailbox_name.data() + mailbox_name.length(),
326 reinterpret_cast<char*>(ack.gl_frame_data->mailbox.name));
327 ack.gl_frame_data->size = texture_to_produce->size();
328 ack.gl_frame_data->sync_point =
329 content::ImageTransportFactory::GetInstance()->InsertSyncPoint();
330 } else if (skip_frame) {
331 // Skip the frame, i.e. tell the producer to reuse the same buffer that
332 // we just received.
333 ack.gl_frame_data->size = received_size;
334 ack.gl_frame_data->mailbox = received_mailbox;
337 RenderWidgetHostImpl::SendSwapCompositorFrameAck(
338 route_id, output_surface_id, renderer_host_id, ack);
341 void AcknowledgeBufferForGpu(
342 int32 route_id,
343 int gpu_host_id,
344 const std::string& received_mailbox,
345 bool skip_frame,
346 const scoped_refptr<ui::Texture>& texture_to_produce) {
347 AcceleratedSurfaceMsg_BufferPresented_Params ack;
348 uint32 sync_point = 0;
349 DCHECK(!texture_to_produce.get() || !skip_frame);
350 if (texture_to_produce.get()) {
351 ack.mailbox_name = texture_to_produce->Produce();
352 sync_point =
353 content::ImageTransportFactory::GetInstance()->InsertSyncPoint();
354 } else if (skip_frame) {
355 ack.mailbox_name = received_mailbox;
356 ack.sync_point = 0;
359 ack.sync_point = sync_point;
360 RenderWidgetHostImpl::AcknowledgeBufferPresent(
361 route_id, gpu_host_id, ack);
364 } // namespace
366 // We need to watch for mouse events outside a Web Popup or its parent
367 // and dismiss the popup for certain events.
368 class RenderWidgetHostViewAura::EventFilterForPopupExit :
369 public ui::EventHandler {
370 public:
371 explicit EventFilterForPopupExit(RenderWidgetHostViewAura* rwhva)
372 : rwhva_(rwhva) {
373 DCHECK(rwhva_);
374 aura::Window* root_window = rwhva_->window_->GetRootWindow();
375 DCHECK(root_window);
376 root_window->AddPreTargetHandler(this);
379 virtual ~EventFilterForPopupExit() {
380 aura::Window* root_window = rwhva_->window_->GetRootWindow();
381 DCHECK(root_window);
382 root_window->RemovePreTargetHandler(this);
385 // Overridden from ui::EventHandler
386 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
387 rwhva_->ApplyEventFilterForPopupExit(event);
390 private:
391 RenderWidgetHostViewAura* rwhva_;
393 DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit);
396 void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
397 ui::MouseEvent* event) {
398 if (in_shutdown_ || is_fullscreen_)
399 return;
401 if (event->type() != ui::ET_MOUSE_PRESSED || !event->target())
402 return;
404 aura::Window* target = static_cast<aura::Window*>(event->target());
405 if (target != window_ &&
406 (!popup_parent_host_view_ ||
407 target != popup_parent_host_view_->window_)) {
408 // Note: popup_parent_host_view_ may be NULL when there are multiple
409 // popup children per view. See: RenderWidgetHostViewAura::InitAsPopup().
410 in_shutdown_ = true;
411 host_->Shutdown();
415 // We have to implement the WindowObserver interface on a separate object
416 // because clang doesn't like implementing multiple interfaces that have
417 // methods with the same name. This object is owned by the
418 // RenderWidgetHostViewAura.
419 class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver {
420 public:
421 explicit WindowObserver(RenderWidgetHostViewAura* view)
422 : view_(view) {
423 view_->window_->AddObserver(this);
426 virtual ~WindowObserver() {
427 view_->window_->RemoveObserver(this);
430 // Overridden from aura::WindowObserver:
431 virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
432 if (window == view_->window_)
433 view_->AddedToRootWindow();
436 virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE {
437 if (window == view_->window_)
438 view_->RemovingFromRootWindow();
441 private:
442 RenderWidgetHostViewAura* view_;
444 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
447 ////////////////////////////////////////////////////////////////////////////////
448 // RenderWidgetHostViewAura, public:
450 RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
451 : host_(RenderWidgetHostImpl::From(host)),
452 window_(new aura::Window(this)),
453 in_shutdown_(false),
454 in_bounds_changed_(false),
455 is_fullscreen_(false),
456 popup_parent_host_view_(NULL),
457 popup_child_host_view_(NULL),
458 is_loading_(false),
459 text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
460 text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
461 can_compose_inline_(true),
462 has_composition_text_(false),
463 accept_return_character_(false),
464 last_output_surface_id_(0),
465 pending_delegated_ack_count_(0),
466 skipped_frames_(false),
467 last_swapped_surface_scale_factor_(1.f),
468 paint_canvas_(NULL),
469 synthetic_move_sent_(false),
470 accelerated_compositing_state_changed_(false),
471 can_lock_compositor_(YES),
472 cursor_visibility_state_in_renderer_(UNKNOWN),
473 paint_observer_(NULL),
474 touch_editing_client_(NULL),
475 delegated_frame_evictor_(new DelegatedFrameEvictor(this)),
476 weak_ptr_factory_(this) {
477 host_->SetView(this);
478 window_observer_.reset(new WindowObserver(this));
479 aura::client::SetTooltipText(window_, &tooltip_);
480 aura::client::SetActivationDelegate(window_, this);
481 aura::client::SetActivationChangeObserver(window_, this);
482 aura::client::SetFocusChangeObserver(window_, this);
483 gfx::Screen::GetScreenFor(window_)->AddObserver(this);
484 software_frame_manager_.reset(new SoftwareFrameManager(
485 weak_ptr_factory_.GetWeakPtr()));
486 #if defined(OS_WIN)
487 plugin_parent_window_ = NULL;
488 #endif
491 ////////////////////////////////////////////////////////////////////////////////
492 // RenderWidgetHostViewAura, RenderWidgetHostView implementation:
494 void RenderWidgetHostViewAura::InitAsChild(
495 gfx::NativeView parent_view) {
496 window_->Init(ui::LAYER_TEXTURED);
497 window_->SetName("RenderWidgetHostViewAura");
500 void RenderWidgetHostViewAura::InitAsPopup(
501 RenderWidgetHostView* parent_host_view,
502 const gfx::Rect& bounds_in_screen) {
503 popup_parent_host_view_ =
504 static_cast<RenderWidgetHostViewAura*>(parent_host_view);
506 RenderWidgetHostViewAura* old_child =
507 popup_parent_host_view_->popup_child_host_view_;
508 if (old_child) {
509 // TODO(jhorwich): Allow multiple popup_child_host_view_ per view, or
510 // similar mechanism to ensure a second popup doesn't cause the first one
511 // to never get a chance to filter events. See crbug.com/160589.
512 DCHECK(old_child->popup_parent_host_view_ == popup_parent_host_view_);
513 old_child->popup_parent_host_view_ = NULL;
515 popup_parent_host_view_->popup_child_host_view_ = this;
516 window_->SetType(aura::client::WINDOW_TYPE_MENU);
517 window_->Init(ui::LAYER_TEXTURED);
518 window_->SetName("RenderWidgetHostViewAura");
520 aura::Window* root = popup_parent_host_view_->window_->GetRootWindow();
521 aura::client::ParentWindowWithContext(window_, root, bounds_in_screen);
523 SetBounds(bounds_in_screen);
524 Show();
527 void RenderWidgetHostViewAura::InitAsFullscreen(
528 RenderWidgetHostView* reference_host_view) {
529 is_fullscreen_ = true;
530 window_->SetType(aura::client::WINDOW_TYPE_NORMAL);
531 window_->Init(ui::LAYER_TEXTURED);
532 window_->SetName("RenderWidgetHostViewAura");
533 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
535 aura::Window* parent = NULL;
536 gfx::Rect bounds;
537 if (reference_host_view) {
538 aura::Window* reference_window =
539 static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_;
540 if (reference_window) {
541 host_tracker_.reset(new aura::WindowTracker);
542 host_tracker_->Add(reference_window);
544 gfx::Display display = gfx::Screen::GetScreenFor(window_)->
545 GetDisplayNearestWindow(reference_window);
546 parent = reference_window->GetRootWindow();
547 bounds = display.bounds();
549 aura::client::ParentWindowWithContext(window_, parent, bounds);
550 Show();
551 Focus();
554 RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
555 return host_;
558 void RenderWidgetHostViewAura::WasShown() {
559 DCHECK(host_);
560 if (!host_->is_hidden())
561 return;
562 host_->WasShown();
563 software_frame_manager_->SetVisibility(true);
564 delegated_frame_evictor_->SetVisible(true);
566 aura::Window* root = window_->GetRootWindow();
567 if (root) {
568 aura::client::CursorClient* cursor_client =
569 aura::client::GetCursorClient(root);
570 if (cursor_client)
571 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
574 if (!current_surface_.get() && host_->is_accelerated_compositing_active() &&
575 !released_front_lock_.get()) {
576 ui::Compositor* compositor = GetCompositor();
577 if (compositor)
578 released_front_lock_ = compositor->GetCompositorLock();
581 #if defined(OS_WIN)
582 LPARAM lparam = reinterpret_cast<LPARAM>(this);
583 EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
585 if (::IsWindow(plugin_parent_window_)) {
586 gfx::Rect window_bounds = window_->GetBoundsInRootWindow();
587 ::SetWindowPos(plugin_parent_window_, NULL, window_bounds.x(),
588 window_bounds.y(), window_bounds.width(),
589 window_bounds.height(), 0);
591 #endif
594 void RenderWidgetHostViewAura::WasHidden() {
595 if (!host_ || host_->is_hidden())
596 return;
597 host_->WasHidden();
598 software_frame_manager_->SetVisibility(false);
599 delegated_frame_evictor_->SetVisible(false);
600 released_front_lock_ = NULL;
602 #if defined(OS_WIN)
603 constrained_rects_.clear();
604 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
605 if (dispatcher) {
606 HWND parent = dispatcher->host()->GetAcceleratedWidget();
607 LPARAM lparam = reinterpret_cast<LPARAM>(this);
609 EnumChildWindows(parent, HideWindowsCallback, lparam);
611 if (::IsWindow(plugin_parent_window_))
612 ::SetWindowPos(plugin_parent_window_, NULL, 0, 0, 0, 0, 0);
613 #endif
616 void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) {
617 // For a SetSize operation, we don't care what coordinate system the origin
618 // of the window is in, it's only important to make sure that the origin
619 // remains constant after the operation.
620 InternalSetBounds(gfx::Rect(window_->bounds().origin(), size));
623 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
624 gfx::Point relative_origin(rect.origin());
626 // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but
627 // Window::SetBounds() takes parent coordinates, so do the conversion here.
628 aura::Window* root = window_->GetRootWindow();
629 if (root) {
630 aura::client::ScreenPositionClient* screen_position_client =
631 aura::client::GetScreenPositionClient(root);
632 if (screen_position_client) {
633 screen_position_client->ConvertPointFromScreen(
634 window_->parent(), &relative_origin);
638 InternalSetBounds(gfx::Rect(relative_origin, rect.size()));
641 void RenderWidgetHostViewAura::MaybeCreateResizeLock() {
642 if (!ShouldCreateResizeLock())
643 return;
644 DCHECK(window_->GetDispatcher());
645 DCHECK(window_->GetDispatcher()->compositor());
647 // Listen to changes in the compositor lock state.
648 ui::Compositor* compositor = window_->GetDispatcher()->compositor();
649 if (!compositor->HasObserver(this))
650 compositor->AddObserver(this);
652 bool defer_compositor_lock =
653 can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
654 can_lock_compositor_ == NO_PENDING_COMMIT;
656 if (can_lock_compositor_ == YES)
657 can_lock_compositor_ = YES_DID_LOCK;
659 resize_lock_ = CreateResizeLock(defer_compositor_lock);
662 bool RenderWidgetHostViewAura::ShouldCreateResizeLock() {
663 // On Windows while resizing, the the resize locks makes us mis-paint a white
664 // vertical strip (including the non-client area) if the content composition
665 // is lagging the UI composition. So here we disable the throttling so that
666 // the UI bits can draw ahead of the content thereby reducing the amount of
667 // whiteout. Because this causes the content to be drawn at wrong sizes while
668 // resizing we compensate by blocking the UI thread in Compositor::Draw() by
669 // issuing a FinishAllRendering() if we are resizing.
670 #if defined (OS_WIN)
671 return false;
672 #endif
674 if (resize_lock_)
675 return false;
677 if (host_->should_auto_resize())
678 return false;
679 if (!host_->is_accelerated_compositing_active())
680 return false;
682 gfx::Size desired_size = window_->bounds().size();
683 if (desired_size == current_frame_size_)
684 return false;
686 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
687 if (!dispatcher)
688 return false;
690 ui::Compositor* compositor = dispatcher->compositor();
691 if (!compositor)
692 return false;
694 return true;
697 scoped_ptr<ResizeLock> RenderWidgetHostViewAura::CreateResizeLock(
698 bool defer_compositor_lock) {
699 gfx::Size desired_size = window_->bounds().size();
700 return scoped_ptr<ResizeLock>(new CompositorResizeLock(
701 window_->GetDispatcher(),
702 desired_size,
703 defer_compositor_lock,
704 base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs)));
707 gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
708 return window_;
711 gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const {
712 #if defined(OS_WIN)
713 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
714 if (dispatcher)
715 return reinterpret_cast<gfx::NativeViewId>(
716 dispatcher->host()->GetAcceleratedWidget());
717 #endif
718 return static_cast<gfx::NativeViewId>(NULL);
721 gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
722 #if defined(OS_WIN)
723 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
724 if (!dispatcher)
725 return static_cast<gfx::NativeViewAccessible>(NULL);
726 HWND hwnd = dispatcher->host()->GetAcceleratedWidget();
728 BrowserAccessibilityManager* manager =
729 GetOrCreateBrowserAccessibilityManager();
730 if (manager)
731 return manager->GetRoot()->ToBrowserAccessibilityWin();
732 #endif
734 NOTIMPLEMENTED();
735 return static_cast<gfx::NativeViewAccessible>(NULL);
738 BrowserAccessibilityManager*
739 RenderWidgetHostViewAura::GetOrCreateBrowserAccessibilityManager() {
740 BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
741 if (manager)
742 return manager;
744 #if defined(OS_WIN)
745 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
746 if (!dispatcher)
747 return NULL;
748 HWND hwnd = dispatcher->host()->GetAcceleratedWidget();
750 // The accessible_parent may be NULL at this point. The WebContents will pass
751 // it down to this instance (by way of the RenderViewHost and
752 // RenderWidgetHost) when it is known. This instance will then set it on its
753 // BrowserAccessibilityManager.
754 gfx::NativeViewAccessible accessible_parent =
755 host_->GetParentNativeViewAccessible();
757 manager = new BrowserAccessibilityManagerWin(
758 hwnd, accessible_parent,
759 BrowserAccessibilityManagerWin::GetEmptyDocument(), this);
760 #else
761 manager = BrowserAccessibilityManager::Create(
762 BrowserAccessibilityManager::GetEmptyDocument(), this);
763 #endif
765 SetBrowserAccessibilityManager(manager);
766 return manager;
769 void RenderWidgetHostViewAura::SetKeyboardFocus() {
770 #if defined(OS_WIN)
771 if (CanFocus()) {
772 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
773 if (dispatcher)
774 ::SetFocus(dispatcher->host()->GetAcceleratedWidget());
776 #endif
779 void RenderWidgetHostViewAura::MovePluginWindows(
780 const gfx::Vector2d& scroll_offset,
781 const std::vector<WebPluginGeometry>& plugin_window_moves) {
782 #if defined(OS_WIN)
783 // We need to clip the rectangle to the tab's viewport, otherwise we will draw
784 // over the browser UI.
785 if (!window_->GetRootWindow()) {
786 DCHECK(plugin_window_moves.empty());
787 return;
789 HWND parent = window_->GetDispatcher()->host()->GetAcceleratedWidget();
790 gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
791 std::vector<WebPluginGeometry> moves = plugin_window_moves;
793 gfx::Rect view_port(scroll_offset.x(), scroll_offset.y(), view_bounds.width(),
794 view_bounds.height());
796 for (size_t i = 0; i < moves.size(); ++i) {
797 gfx::Rect clip(moves[i].clip_rect);
798 gfx::Vector2d view_port_offset(
799 moves[i].window_rect.OffsetFromOrigin() + scroll_offset);
800 clip.Offset(view_port_offset);
801 clip.Intersect(view_port);
802 clip.Offset(-view_port_offset);
803 moves[i].clip_rect = clip;
805 moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin());
807 plugin_window_moves_[moves[i].window] = moves[i];
809 // constrained_rects_ are relative to the root window. We want to convert
810 // them to be relative to the plugin window.
811 for (size_t j = 0; j < constrained_rects_.size(); ++j) {
812 gfx::Rect offset_cutout = constrained_rects_[j];
813 offset_cutout -= moves[i].window_rect.OffsetFromOrigin();
814 moves[i].cutout_rects.push_back(offset_cutout);
818 MovePluginWindowsHelper(parent, moves);
820 // Make sure each plugin window (or its wrapper if it exists) has a pointer to
821 // |this|.
822 for (size_t i = 0; i < moves.size(); ++i) {
823 HWND window = moves[i].window;
824 if (GetParent(window) != parent) {
825 window = GetParent(window);
827 if (!GetProp(window, kWidgetOwnerProperty))
828 SetProp(window, kWidgetOwnerProperty, this);
830 #endif // defined(OS_WIN)
833 void RenderWidgetHostViewAura::Focus() {
834 // Make sure we have a FocusClient before attempting to Focus(). In some
835 // situations we may not yet be in a valid Window hierarchy (such as reloading
836 // after out of memory discarded the tab).
837 aura::client::FocusClient* client = aura::client::GetFocusClient(window_);
838 if (client)
839 window_->Focus();
842 void RenderWidgetHostViewAura::Blur() {
843 window_->Blur();
846 bool RenderWidgetHostViewAura::HasFocus() const {
847 return window_->HasFocus();
850 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
851 return CanCopyToBitmap() || !!host_->GetBackingStore(false);
854 void RenderWidgetHostViewAura::Show() {
855 window_->Show();
856 WasShown();
859 void RenderWidgetHostViewAura::Hide() {
860 window_->Hide();
861 WasHidden();
864 bool RenderWidgetHostViewAura::IsShowing() {
865 return window_->IsVisible();
868 gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
869 // This is the size that we want the renderer to produce. While we're waiting
870 // for the correct frame (i.e. during a resize), don't change the size so that
871 // we don't pipeline more resizes than we can handle.
872 gfx::Rect bounds(window_->GetBoundsInScreen());
873 if (resize_lock_.get())
874 return gfx::Rect(bounds.origin(), resize_lock_->expected_size());
875 else
876 return bounds;
879 void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) {
880 RenderWidgetHostViewBase::SetBackground(background);
881 host_->SetBackground(background);
882 window_->layer()->SetFillsBoundsOpaquely(background.isOpaque());
885 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
886 current_cursor_ = cursor;
887 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
888 GetDisplayNearestWindow(window_);
889 current_cursor_.SetDisplayInfo(display);
890 UpdateCursorIfOverSelf();
893 void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
894 if (is_loading_ && !is_loading && paint_observer_)
895 paint_observer_->OnPageLoadComplete();
896 is_loading_ = is_loading;
897 UpdateCursorIfOverSelf();
900 void RenderWidgetHostViewAura::TextInputTypeChanged(
901 ui::TextInputType type,
902 ui::TextInputMode input_mode,
903 bool can_compose_inline) {
904 if (text_input_type_ != type ||
905 text_input_mode_ != input_mode ||
906 can_compose_inline_ != can_compose_inline) {
907 text_input_type_ = type;
908 text_input_mode_ = input_mode;
909 can_compose_inline_ = can_compose_inline;
910 if (GetInputMethod())
911 GetInputMethod()->OnTextInputTypeChanged(this);
912 if (touch_editing_client_)
913 touch_editing_client_->OnTextInputTypeChanged(text_input_type_);
917 void RenderWidgetHostViewAura::ImeCancelComposition() {
918 if (GetInputMethod())
919 GetInputMethod()->CancelComposition(this);
920 has_composition_text_ = false;
923 void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
924 const gfx::Range& range,
925 const std::vector<gfx::Rect>& character_bounds) {
926 composition_character_bounds_ = character_bounds;
929 void RenderWidgetHostViewAura::DidUpdateBackingStore(
930 const gfx::Rect& scroll_rect,
931 const gfx::Vector2d& scroll_delta,
932 const std::vector<gfx::Rect>& copy_rects,
933 const ui::LatencyInfo& latency_info) {
934 if (accelerated_compositing_state_changed_)
935 UpdateExternalTexture();
937 software_latency_info_.MergeWith(latency_info);
939 // Use the state of the RenderWidgetHost and not the window as the two may
940 // differ. In particular if the window is hidden but the renderer isn't and we
941 // ignore the update and the window is made visible again the layer isn't
942 // marked as dirty and we show the wrong thing.
943 // We do this after UpdateExternalTexture() so that when we become visible
944 // we're not drawing a stale texture.
945 if (host_->is_hidden())
946 return;
948 gfx::Rect clip_rect;
949 if (paint_canvas_) {
950 SkRect sk_clip_rect;
951 if (paint_canvas_->sk_canvas()->getClipBounds(&sk_clip_rect))
952 clip_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(sk_clip_rect));
955 if (!scroll_rect.IsEmpty())
956 SchedulePaintIfNotInClip(scroll_rect, clip_rect);
958 #if defined(OS_WIN)
959 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
960 #endif
961 for (size_t i = 0; i < copy_rects.size(); ++i) {
962 gfx::Rect rect = gfx::SubtractRects(copy_rects[i], scroll_rect);
963 if (rect.IsEmpty())
964 continue;
966 SchedulePaintIfNotInClip(rect, clip_rect);
968 #if defined(OS_WIN)
969 if (dispatcher) {
970 // Send the invalid rect in screen coordinates.
971 gfx::Rect screen_rect = GetViewBounds();
972 gfx::Rect invalid_screen_rect(rect);
973 invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y());
974 HWND hwnd = dispatcher->host()->GetAcceleratedWidget();
975 PaintPluginWindowsHelper(hwnd, invalid_screen_rect);
977 #endif // defined(OS_WIN)
981 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
982 int error_code) {
983 UpdateCursorIfOverSelf();
984 Destroy();
987 void RenderWidgetHostViewAura::Destroy() {
988 // Beware, this function is not called on all destruction paths. It will
989 // implicitly end up calling ~RenderWidgetHostViewAura though, so all
990 // destruction/cleanup code should happen there, not here.
991 in_shutdown_ = true;
992 delete window_;
995 void RenderWidgetHostViewAura::SetTooltipText(
996 const base::string16& tooltip_text) {
997 tooltip_ = tooltip_text;
998 aura::Window* root_window = window_->GetRootWindow();
999 aura::client::TooltipClient* tooltip_client =
1000 aura::client::GetTooltipClient(root_window);
1001 if (tooltip_client) {
1002 tooltip_client->UpdateTooltip(window_);
1003 // Content tooltips should be visible indefinitely.
1004 tooltip_client->SetTooltipShownTimeout(window_, 0);
1008 void RenderWidgetHostViewAura::SelectionChanged(const base::string16& text,
1009 size_t offset,
1010 const gfx::Range& range) {
1011 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
1013 #if defined(USE_X11) && !defined(OS_CHROMEOS)
1014 if (text.empty() || range.is_empty())
1015 return;
1017 // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard.
1018 ui::ScopedClipboardWriter clipboard_writer(
1019 ui::Clipboard::GetForCurrentThread(),
1020 ui::CLIPBOARD_TYPE_SELECTION);
1021 clipboard_writer.WriteText(text);
1022 #endif // defined(USE_X11) && !defined(OS_CHROMEOS)
1025 void RenderWidgetHostViewAura::SelectionBoundsChanged(
1026 const ViewHostMsg_SelectionBounds_Params& params) {
1027 if (selection_anchor_rect_ == params.anchor_rect &&
1028 selection_focus_rect_ == params.focus_rect)
1029 return;
1031 selection_anchor_rect_ = params.anchor_rect;
1032 selection_focus_rect_ = params.focus_rect;
1034 if (GetInputMethod())
1035 GetInputMethod()->OnCaretBoundsChanged(this);
1037 if (touch_editing_client_) {
1038 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
1039 selection_focus_rect_);
1043 void RenderWidgetHostViewAura::ScrollOffsetChanged() {
1044 aura::Window* root = window_->GetRootWindow();
1045 if (!root)
1046 return;
1047 aura::client::CursorClient* cursor_client =
1048 aura::client::GetCursorClient(root);
1049 if (cursor_client && !cursor_client->IsCursorVisible())
1050 cursor_client->DisableMouseEvents();
1053 BackingStore* RenderWidgetHostViewAura::AllocBackingStore(
1054 const gfx::Size& size) {
1055 return new BackingStoreAura(host_, size);
1058 void RenderWidgetHostViewAura::CopyFromCompositingSurface(
1059 const gfx::Rect& src_subrect,
1060 const gfx::Size& dst_size,
1061 const base::Callback<void(bool, const SkBitmap&)>& callback) {
1062 if (!CanCopyToBitmap()) {
1063 callback.Run(false, SkBitmap());
1064 return;
1067 const gfx::Size& dst_size_in_pixel = ConvertViewSizeToPixel(this, dst_size);
1068 scoped_ptr<cc::CopyOutputRequest> request =
1069 cc::CopyOutputRequest::CreateRequest(base::Bind(
1070 &RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult,
1071 dst_size_in_pixel,
1072 callback));
1073 gfx::Rect src_subrect_in_pixel =
1074 ConvertRectToPixel(current_device_scale_factor_, src_subrect);
1075 request->set_area(src_subrect_in_pixel);
1076 window_->layer()->RequestCopyOfOutput(request.Pass());
1079 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
1080 const gfx::Rect& src_subrect,
1081 const scoped_refptr<media::VideoFrame>& target,
1082 const base::Callback<void(bool)>& callback) {
1083 if (!CanCopyToVideoFrame()) {
1084 callback.Run(false);
1085 return;
1088 // Try get a texture to reuse.
1089 scoped_refptr<OwnedMailbox> subscriber_texture;
1090 if (frame_subscriber_) {
1091 if (!idle_frame_subscriber_textures_.empty()) {
1092 subscriber_texture = idle_frame_subscriber_textures_.back();
1093 idle_frame_subscriber_textures_.pop_back();
1094 } else if (GLHelper* helper =
1095 ImageTransportFactory::GetInstance()->GetGLHelper()) {
1096 subscriber_texture = new OwnedMailbox(helper);
1100 scoped_ptr<cc::CopyOutputRequest> request =
1101 cc::CopyOutputRequest::CreateRequest(base::Bind(
1102 &RenderWidgetHostViewAura::
1103 CopyFromCompositingSurfaceHasResultForVideo,
1104 AsWeakPtr(), // For caching the ReadbackYUVInterface on this class.
1105 subscriber_texture,
1106 target,
1107 callback));
1108 gfx::Rect src_subrect_in_pixel =
1109 ConvertRectToPixel(current_device_scale_factor_, src_subrect);
1110 request->set_area(src_subrect_in_pixel);
1111 if (subscriber_texture) {
1112 request->SetTextureMailbox(cc::TextureMailbox(
1113 subscriber_texture->mailbox(), subscriber_texture->sync_point()));
1115 window_->layer()->RequestCopyOfOutput(request.Pass());
1118 bool RenderWidgetHostViewAura::CanCopyToBitmap() const {
1119 return GetCompositor() && window_->layer()->has_external_content();
1122 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
1123 return GetCompositor() &&
1124 window_->layer()->has_external_content() &&
1125 host_->is_accelerated_compositing_active();
1128 bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
1129 return true;
1132 void RenderWidgetHostViewAura::BeginFrameSubscription(
1133 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1134 frame_subscriber_ = subscriber.Pass();
1137 void RenderWidgetHostViewAura::EndFrameSubscription() {
1138 idle_frame_subscriber_textures_.clear();
1139 frame_subscriber_.reset();
1142 void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() {
1143 // Delay processing the state change until we either get a software frame if
1144 // switching to software mode or receive a buffers swapped notification
1145 // if switching to accelerated mode.
1146 // Sometimes (e.g. on a page load) the renderer will spuriously disable then
1147 // re-enable accelerated compositing, causing us to flash.
1148 // TODO(piman): factor the enable/disable accelerated compositing message into
1149 // the UpdateRect/AcceleratedSurfaceBuffersSwapped messages so that we have
1150 // fewer inconsistent temporary states.
1151 accelerated_compositing_state_changed_ = true;
1154 void RenderWidgetHostViewAura::AcceleratedSurfaceInitialized(int host_id,
1155 int route_id) {
1158 bool RenderWidgetHostViewAura::ShouldSkipFrame(gfx::Size size_in_dip) const {
1159 if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
1160 can_lock_compositor_ == NO_PENDING_COMMIT ||
1161 !resize_lock_.get())
1162 return false;
1164 return size_in_dip != resize_lock_->expected_size();
1167 void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
1168 if (HasDisplayPropertyChanged(window_))
1169 host_->InvalidateScreenInfo();
1171 // Don't recursively call SetBounds if this bounds update is the result of
1172 // a Window::SetBoundsInternal call.
1173 if (!in_bounds_changed_)
1174 window_->SetBounds(rect);
1175 host_->WasResized();
1176 MaybeCreateResizeLock();
1177 if (touch_editing_client_) {
1178 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
1179 selection_focus_rect_);
1181 #if defined(OS_WIN)
1182 // Create the dummy plugin parent window which will be passed as the
1183 // container window to windowless plugins.
1184 // Plugins like Flash assume the container window which is returned via the
1185 // NPNVnetscapeWindow property corresponds to the bounds of the webpage.
1186 // This is not true in Aura where we have only HWND which is the main Aura
1187 // window. If we return this window to plugins like Flash then it causes the
1188 // coordinate translations done by these plugins to break.
1189 if (!plugin_parent_window_ && GetNativeViewId()) {
1190 plugin_parent_window_ = ::CreateWindowEx(
1191 0, L"Static", NULL, WS_CHILDWINDOW, 0, 0, 0, 0,
1192 reinterpret_cast<HWND>(GetNativeViewId()), NULL, NULL, NULL);
1193 if (::IsWindow(plugin_parent_window_))
1194 ::SetProp(plugin_parent_window_, content::kPluginDummyParentProperty,
1195 reinterpret_cast<HANDLE>(true));
1197 if (::IsWindow(plugin_parent_window_)) {
1198 gfx::Rect window_bounds = window_->GetBoundsInRootWindow();
1199 ::SetWindowPos(plugin_parent_window_, NULL, window_bounds.x(),
1200 window_bounds.y(), window_bounds.width(),
1201 window_bounds.height(), 0);
1203 #endif
1206 void RenderWidgetHostViewAura::CheckResizeLock() {
1207 if (!resize_lock_ || resize_lock_->expected_size() != current_frame_size_)
1208 return;
1210 // Since we got the size we were looking for, unlock the compositor. But delay
1211 // the release of the lock until we've kicked a frame with the new texture, to
1212 // avoid resizing the UI before we have a chance to draw a "good" frame.
1213 resize_lock_->UnlockCompositor();
1214 ui::Compositor* compositor = GetCompositor();
1215 if (compositor) {
1216 if (!compositor->HasObserver(this))
1217 compositor->AddObserver(this);
1221 void RenderWidgetHostViewAura::UpdateExternalTexture() {
1222 // Delay processing accelerated compositing state change till here where we
1223 // act upon the state change. (Clear the external texture if switching to
1224 // software mode or set the external texture if going to accelerated mode).
1225 if (accelerated_compositing_state_changed_)
1226 accelerated_compositing_state_changed_ = false;
1228 bool is_compositing_active = host_->is_accelerated_compositing_active();
1229 if (is_compositing_active && current_surface_.get()) {
1230 window_->layer()->SetExternalTexture(current_surface_.get());
1231 current_frame_size_ = ConvertSizeToDIP(
1232 current_surface_->device_scale_factor(), current_surface_->size());
1233 CheckResizeLock();
1234 software_frame_manager_->DiscardCurrentFrame();
1235 } else if (is_compositing_active &&
1236 software_frame_manager_->HasCurrentFrame()) {
1237 cc::TextureMailbox mailbox;
1238 scoped_ptr<cc::SingleReleaseCallback> callback;
1239 software_frame_manager_->GetCurrentFrameMailbox(&mailbox, &callback);
1240 window_->layer()->SetTextureMailbox(mailbox,
1241 callback.Pass(),
1242 last_swapped_surface_scale_factor_);
1243 current_frame_size_ = ConvertSizeToDIP(last_swapped_surface_scale_factor_,
1244 mailbox.shared_memory_size());
1245 CheckResizeLock();
1246 } else {
1247 window_->layer()->SetShowPaintedContent();
1248 resize_lock_.reset();
1249 host_->WasResized();
1250 software_frame_manager_->DiscardCurrentFrame();
1254 bool RenderWidgetHostViewAura::SwapBuffersPrepare(
1255 const gfx::Rect& surface_rect,
1256 float surface_scale_factor,
1257 const gfx::Rect& damage_rect,
1258 const std::string& mailbox_name,
1259 const BufferPresentedCallback& ack_callback) {
1260 if (last_swapped_surface_size_ != surface_rect.size()) {
1261 // The surface could have shrunk since we skipped an update, in which
1262 // case we can expect a full update.
1263 DLOG_IF(ERROR, damage_rect != surface_rect) << "Expected full damage rect";
1264 skipped_damage_.setEmpty();
1265 last_swapped_surface_size_ = surface_rect.size();
1266 last_swapped_surface_scale_factor_ = surface_scale_factor;
1269 if (ShouldSkipFrame(ConvertSizeToDIP(surface_scale_factor,
1270 surface_rect.size())) ||
1271 mailbox_name.empty()) {
1272 skipped_damage_.op(RectToSkIRect(damage_rect), SkRegion::kUnion_Op);
1273 ack_callback.Run(true, scoped_refptr<ui::Texture>());
1274 return false;
1277 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
1278 current_surface_ =
1279 factory->CreateTransportClient(surface_scale_factor);
1280 if (!current_surface_.get()) {
1281 LOG(ERROR) << "Failed to create ImageTransport texture";
1282 ack_callback.Run(true, scoped_refptr<ui::Texture>());
1283 return false;
1286 current_surface_->Consume(mailbox_name, surface_rect.size());
1287 released_front_lock_ = NULL;
1288 UpdateExternalTexture();
1290 return true;
1293 void RenderWidgetHostViewAura::SwapBuffersCompleted(
1294 const BufferPresentedCallback& ack_callback,
1295 const scoped_refptr<ui::Texture>& texture_to_return) {
1296 ui::Compositor* compositor = GetCompositor();
1297 if (!compositor) {
1298 ack_callback.Run(false, texture_to_return);
1299 } else {
1300 AddOnCommitCallbackAndDisableLocks(
1301 base::Bind(ack_callback, false, texture_to_return));
1304 DidReceiveFrameFromRenderer();
1307 void RenderWidgetHostViewAura::DidReceiveFrameFromRenderer() {
1308 if (frame_subscriber() && CanCopyToVideoFrame()) {
1309 const base::Time present_time = base::Time::Now();
1310 scoped_refptr<media::VideoFrame> frame;
1311 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
1312 if (frame_subscriber()->ShouldCaptureFrame(present_time,
1313 &frame, &callback)) {
1314 CopyFromCompositingSurfaceToVideoFrame(
1315 gfx::Rect(current_frame_size_),
1316 frame,
1317 base::Bind(callback, present_time));
1322 #if defined(OS_WIN)
1323 void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
1324 const std::vector<gfx::Rect>& rects) {
1325 if (rects == constrained_rects_)
1326 return;
1327 constrained_rects_ = rects;
1328 UpdateCutoutRects();
1331 void RenderWidgetHostViewAura::UpdateCutoutRects() {
1332 if (!window_->GetRootWindow())
1333 return;
1334 HWND parent = window_->GetDispatcher()->host()->GetAcceleratedWidget();
1335 CutoutRectsParams params;
1336 params.widget = this;
1337 params.cutout_rects = constrained_rects_;
1338 params.geometry = &plugin_window_moves_;
1339 LPARAM lparam = reinterpret_cast<LPARAM>(&params);
1340 EnumChildWindows(parent, SetCutoutRectsCallback, lparam);
1342 #endif
1344 void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
1345 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
1346 int gpu_host_id) {
1347 BufferPresentedCallback ack_callback = base::Bind(
1348 &AcknowledgeBufferForGpu,
1349 params_in_pixel.route_id,
1350 gpu_host_id,
1351 params_in_pixel.mailbox_name);
1352 BuffersSwapped(params_in_pixel.size,
1353 gfx::Rect(params_in_pixel.size),
1354 params_in_pixel.scale_factor,
1355 params_in_pixel.mailbox_name,
1356 params_in_pixel.latency_info,
1357 ack_callback);
1360 void RenderWidgetHostViewAura::SwapDelegatedFrame(
1361 uint32 output_surface_id,
1362 scoped_ptr<cc::DelegatedFrameData> frame_data,
1363 float frame_device_scale_factor,
1364 const ui::LatencyInfo& latency_info) {
1365 DCHECK_NE(0u, frame_data->render_pass_list.size());
1367 cc::RenderPass* root_pass = frame_data->render_pass_list.back();
1369 gfx::Size frame_size = root_pass->output_rect.size();
1370 gfx::Size frame_size_in_dip =
1371 ConvertSizeToDIP(frame_device_scale_factor, frame_size);
1373 gfx::Rect damage_rect = gfx::ToEnclosingRect(root_pass->damage_rect);
1374 damage_rect.Intersect(gfx::Rect(frame_size));
1375 gfx::Rect damage_rect_in_dip =
1376 ConvertRectToDIP(frame_device_scale_factor, damage_rect);
1378 software_frame_manager_->DiscardCurrentFrame();
1380 if (ShouldSkipFrame(frame_size_in_dip)) {
1381 cc::CompositorFrameAck ack;
1382 cc::TransferableResource::ReturnResources(frame_data->resource_list,
1383 &ack.resources);
1384 RenderWidgetHostImpl::SendSwapCompositorFrameAck(
1385 host_->GetRoutingID(), output_surface_id,
1386 host_->GetProcess()->GetID(), ack);
1387 skipped_frames_ = true;
1388 return;
1391 if (skipped_frames_) {
1392 skipped_frames_ = false;
1393 damage_rect = gfx::Rect(frame_size);
1394 damage_rect_in_dip = gfx::Rect(frame_size_in_dip);
1396 // Give the same damage rect to the compositor.
1397 cc::RenderPass* root_pass = frame_data->render_pass_list.back();
1398 root_pass->damage_rect = damage_rect;
1401 if (output_surface_id != last_output_surface_id_) {
1402 // Resource ids are scoped by the output surface.
1403 // If the originating output surface doesn't match the last one, it
1404 // indicates the renderer's output surface may have been recreated, in which
1405 // case we should recreate the DelegatedRendererLayer, to avoid matching
1406 // resources from the old one with resources from the new one which would
1407 // have the same id. Changing the layer to showing painted content destroys
1408 // the DelegatedRendererLayer.
1409 EvictDelegatedFrame();
1411 // Drop the cc::DelegatedFrameResourceCollection so that we will not return
1412 // any resources from the old output surface with the new output surface id.
1413 if (resource_collection_.get()) {
1414 resource_collection_->SetClient(NULL);
1416 if (resource_collection_->LoseAllResources())
1417 SendReturnedDelegatedResources(last_output_surface_id_);
1419 resource_collection_ = NULL;
1421 last_output_surface_id_ = output_surface_id;
1423 if (frame_size.IsEmpty()) {
1424 DCHECK_EQ(0u, frame_data->resource_list.size());
1425 EvictDelegatedFrame();
1426 } else {
1427 if (!resource_collection_) {
1428 resource_collection_ = new cc::DelegatedFrameResourceCollection;
1429 resource_collection_->SetClient(this);
1431 // If the physical frame size changes, we need a new |frame_provider_|. If
1432 // the physical frame size is the same, but the size in DIP changed, we
1433 // need to adjust the scale at which the frames will be drawn, and we do
1434 // this by making a new |frame_provider_| also to ensure the scale change
1435 // is presented in sync with the new frame content.
1436 if (!frame_provider_.get() || frame_size != frame_provider_->frame_size() ||
1437 frame_size_in_dip != current_frame_size_) {
1438 frame_provider_ = new cc::DelegatedFrameProvider(
1439 resource_collection_.get(), frame_data.Pass());
1440 window_->layer()->SetShowDelegatedContent(frame_provider_.get(),
1441 frame_size_in_dip);
1442 } else {
1443 frame_provider_->SetFrameData(frame_data.Pass());
1446 released_front_lock_ = NULL;
1447 current_frame_size_ = frame_size_in_dip;
1448 CheckResizeLock();
1450 if (paint_observer_)
1451 paint_observer_->OnUpdateCompositorContent();
1452 window_->SchedulePaintInRect(damage_rect_in_dip);
1454 pending_delegated_ack_count_++;
1456 ui::Compositor* compositor = GetCompositor();
1457 if (!compositor) {
1458 SendDelegatedFrameAck(output_surface_id);
1459 } else {
1460 compositor->SetLatencyInfo(latency_info);
1461 AddOnCommitCallbackAndDisableLocks(
1462 base::Bind(&RenderWidgetHostViewAura::SendDelegatedFrameAck,
1463 AsWeakPtr(),
1464 output_surface_id));
1466 DidReceiveFrameFromRenderer();
1467 if (frame_provider_.get())
1468 delegated_frame_evictor_->SwappedFrame(!host_->is_hidden());
1469 // Note: the frame may have been evicted immediately.
1472 void RenderWidgetHostViewAura::SendDelegatedFrameAck(uint32 output_surface_id) {
1473 cc::CompositorFrameAck ack;
1474 if (resource_collection_)
1475 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
1476 RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(),
1477 output_surface_id,
1478 host_->GetProcess()->GetID(),
1479 ack);
1480 DCHECK_GT(pending_delegated_ack_count_, 0);
1481 pending_delegated_ack_count_--;
1484 void RenderWidgetHostViewAura::UnusedResourcesAreAvailable() {
1485 if (pending_delegated_ack_count_)
1486 return;
1488 SendReturnedDelegatedResources(last_output_surface_id_);
1491 void RenderWidgetHostViewAura::SendReturnedDelegatedResources(
1492 uint32 output_surface_id) {
1493 cc::CompositorFrameAck ack;
1494 if (resource_collection_)
1495 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
1496 DCHECK(!ack.resources.empty());
1497 RenderWidgetHostImpl::SendReclaimCompositorResources(
1498 host_->GetRoutingID(),
1499 output_surface_id,
1500 host_->GetProcess()->GetID(),
1501 ack);
1504 void RenderWidgetHostViewAura::EvictDelegatedFrame() {
1505 window_->layer()->SetShowPaintedContent();
1506 frame_provider_ = NULL;
1507 delegated_frame_evictor_->DiscardedFrame();
1510 void RenderWidgetHostViewAura::SwapSoftwareFrame(
1511 uint32 output_surface_id,
1512 scoped_ptr<cc::SoftwareFrameData> frame_data,
1513 float frame_device_scale_factor,
1514 const ui::LatencyInfo& latency_info) {
1515 const gfx::Size& frame_size = frame_data->size;
1516 const gfx::Rect& damage_rect = frame_data->damage_rect;
1517 gfx::Size frame_size_in_dip =
1518 ConvertSizeToDIP(frame_device_scale_factor, frame_size);
1519 if (ShouldSkipFrame(frame_size_in_dip)) {
1520 ReleaseSoftwareFrame(output_surface_id, frame_data->id);
1521 SendSoftwareFrameAck(output_surface_id);
1522 return;
1525 if (!software_frame_manager_->SwapToNewFrame(
1526 output_surface_id,
1527 frame_data.get(),
1528 frame_device_scale_factor,
1529 host_->GetProcess()->GetHandle())) {
1530 ReleaseSoftwareFrame(output_surface_id, frame_data->id);
1531 SendSoftwareFrameAck(output_surface_id);
1532 return;
1535 if (last_swapped_surface_size_ != frame_size) {
1536 DLOG_IF(ERROR, damage_rect != gfx::Rect(frame_size))
1537 << "Expected full damage rect";
1539 last_swapped_surface_size_ = frame_size;
1540 last_swapped_surface_scale_factor_ = frame_device_scale_factor;
1542 cc::TextureMailbox mailbox;
1543 scoped_ptr<cc::SingleReleaseCallback> callback;
1544 software_frame_manager_->GetCurrentFrameMailbox(&mailbox, &callback);
1545 DCHECK(mailbox.IsSharedMemory());
1546 current_frame_size_ = frame_size_in_dip;
1548 released_front_lock_ = NULL;
1549 CheckResizeLock();
1550 window_->layer()->SetTextureMailbox(mailbox,
1551 callback.Pass(),
1552 frame_device_scale_factor);
1553 window_->SchedulePaintInRect(
1554 ConvertRectToDIP(frame_device_scale_factor, damage_rect));
1556 ui::Compositor* compositor = GetCompositor();
1557 if (compositor) {
1558 compositor->SetLatencyInfo(latency_info);
1559 AddOnCommitCallbackAndDisableLocks(
1560 base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck,
1561 AsWeakPtr(),
1562 output_surface_id));
1564 if (paint_observer_)
1565 paint_observer_->OnUpdateCompositorContent();
1566 DidReceiveFrameFromRenderer();
1568 software_frame_manager_->SwapToNewFrameComplete(!host_->is_hidden());
1571 void RenderWidgetHostViewAura::SendSoftwareFrameAck(uint32 output_surface_id) {
1572 unsigned software_frame_id = 0;
1573 if (released_software_frame_ &&
1574 released_software_frame_->output_surface_id == output_surface_id) {
1575 software_frame_id = released_software_frame_->frame_id;
1576 released_software_frame_.reset();
1579 cc::CompositorFrameAck ack;
1580 ack.last_software_frame_id = software_frame_id;
1581 RenderWidgetHostImpl::SendSwapCompositorFrameAck(
1582 host_->GetRoutingID(), output_surface_id,
1583 host_->GetProcess()->GetID(), ack);
1584 SendReclaimSoftwareFrames();
1587 void RenderWidgetHostViewAura::SendReclaimSoftwareFrames() {
1588 if (!released_software_frame_)
1589 return;
1590 cc::CompositorFrameAck ack;
1591 ack.last_software_frame_id = released_software_frame_->frame_id;
1592 RenderWidgetHostImpl::SendReclaimCompositorResources(
1593 host_->GetRoutingID(),
1594 released_software_frame_->output_surface_id,
1595 host_->GetProcess()->GetID(),
1596 ack);
1597 released_software_frame_.reset();
1600 void RenderWidgetHostViewAura::ReleaseSoftwareFrame(
1601 uint32 output_surface_id,
1602 unsigned software_frame_id) {
1603 SendReclaimSoftwareFrames();
1604 DCHECK(!released_software_frame_);
1605 released_software_frame_.reset(new ReleasedFrameInfo(
1606 output_surface_id, software_frame_id));
1609 void RenderWidgetHostViewAura::OnSwapCompositorFrame(
1610 uint32 output_surface_id,
1611 scoped_ptr<cc::CompositorFrame> frame) {
1612 TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
1613 if (frame->delegated_frame_data) {
1614 SwapDelegatedFrame(output_surface_id,
1615 frame->delegated_frame_data.Pass(),
1616 frame->metadata.device_scale_factor,
1617 frame->metadata.latency_info);
1618 return;
1621 if (frame->software_frame_data) {
1622 SwapSoftwareFrame(output_surface_id,
1623 frame->software_frame_data.Pass(),
1624 frame->metadata.device_scale_factor,
1625 frame->metadata.latency_info);
1626 return;
1629 if (!frame->gl_frame_data || frame->gl_frame_data->mailbox.IsZero())
1630 return;
1632 BufferPresentedCallback ack_callback = base::Bind(
1633 &SendCompositorFrameAck,
1634 host_->GetRoutingID(), output_surface_id, host_->GetProcess()->GetID(),
1635 frame->gl_frame_data->mailbox, frame->gl_frame_data->size);
1637 if (!frame->gl_frame_data->sync_point) {
1638 LOG(ERROR) << "CompositorFrame without sync point. Skipping frame...";
1639 ack_callback.Run(true, scoped_refptr<ui::Texture>());
1640 return;
1643 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
1644 factory->WaitSyncPoint(frame->gl_frame_data->sync_point);
1646 std::string mailbox_name(
1647 reinterpret_cast<const char*>(frame->gl_frame_data->mailbox.name),
1648 sizeof(frame->gl_frame_data->mailbox.name));
1649 BuffersSwapped(frame->gl_frame_data->size,
1650 frame->gl_frame_data->sub_buffer_rect,
1651 frame->metadata.device_scale_factor,
1652 mailbox_name,
1653 frame->metadata.latency_info,
1654 ack_callback);
1657 #if defined(OS_WIN)
1658 void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
1659 gfx::NativeViewAccessible accessible_parent) {
1660 if (GetBrowserAccessibilityManager()) {
1661 GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerWin()
1662 ->set_parent_iaccessible(accessible_parent);
1666 gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
1667 const {
1668 return reinterpret_cast<gfx::NativeViewId>(plugin_parent_window_);
1670 #endif
1672 void RenderWidgetHostViewAura::BuffersSwapped(
1673 const gfx::Size& surface_size,
1674 const gfx::Rect& damage_rect,
1675 float surface_scale_factor,
1676 const std::string& mailbox_name,
1677 const ui::LatencyInfo& latency_info,
1678 const BufferPresentedCallback& ack_callback) {
1679 scoped_refptr<ui::Texture> previous_texture(current_surface_);
1680 const gfx::Rect surface_rect = gfx::Rect(surface_size);
1681 software_frame_manager_->DiscardCurrentFrame();
1683 if (!SwapBuffersPrepare(surface_rect,
1684 surface_scale_factor,
1685 damage_rect,
1686 mailbox_name,
1687 ack_callback)) {
1688 return;
1691 SkRegion damage(RectToSkIRect(damage_rect));
1692 if (!skipped_damage_.isEmpty()) {
1693 damage.op(skipped_damage_, SkRegion::kUnion_Op);
1694 skipped_damage_.setEmpty();
1697 DCHECK(surface_rect.Contains(SkIRectToRect(damage.getBounds())));
1698 ui::Texture* current_texture = current_surface_.get();
1700 const gfx::Size surface_size_in_pixel = surface_size;
1701 DLOG_IF(ERROR, previous_texture.get() &&
1702 previous_texture->size() != current_texture->size() &&
1703 SkIRectToRect(damage.getBounds()) != surface_rect) <<
1704 "Expected full damage rect after size change";
1705 if (previous_texture.get() && !previous_damage_.isEmpty() &&
1706 previous_texture->size() == current_texture->size()) {
1707 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
1708 GLHelper* gl_helper = factory->GetGLHelper();
1709 gl_helper->CopySubBufferDamage(
1710 current_texture->PrepareTexture(),
1711 previous_texture->PrepareTexture(),
1712 damage,
1713 previous_damage_);
1715 previous_damage_ = damage;
1717 ui::Compositor* compositor = GetCompositor();
1718 if (compositor) {
1719 // Co-ordinates come in OpenGL co-ordinate space.
1720 // We need to convert to layer space.
1721 gfx::Rect rect_to_paint =
1722 ConvertRectToDIP(surface_scale_factor,
1723 gfx::Rect(damage_rect.x(),
1724 surface_size_in_pixel.height() -
1725 damage_rect.y() - damage_rect.height(),
1726 damage_rect.width(),
1727 damage_rect.height()));
1729 // Damage may not have been DIP aligned, so inflate damage to compensate
1730 // for any round-off error.
1731 rect_to_paint.Inset(-1, -1);
1732 rect_to_paint.Intersect(window_->bounds());
1734 if (paint_observer_)
1735 paint_observer_->OnUpdateCompositorContent();
1736 window_->SchedulePaintInRect(rect_to_paint);
1737 compositor->SetLatencyInfo(latency_info);
1740 SwapBuffersCompleted(ack_callback, previous_texture);
1743 void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
1744 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel,
1745 int gpu_host_id) {
1746 gfx::Rect damage_rect(params_in_pixel.x,
1747 params_in_pixel.y,
1748 params_in_pixel.width,
1749 params_in_pixel.height);
1750 BufferPresentedCallback ack_callback =
1751 base::Bind(&AcknowledgeBufferForGpu,
1752 params_in_pixel.route_id,
1753 gpu_host_id,
1754 params_in_pixel.mailbox_name);
1755 BuffersSwapped(params_in_pixel.surface_size,
1756 damage_rect,
1757 params_in_pixel.surface_scale_factor,
1758 params_in_pixel.mailbox_name,
1759 params_in_pixel.latency_info,
1760 ack_callback);
1763 void RenderWidgetHostViewAura::AcceleratedSurfaceSuspend() {
1766 void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() {
1767 // This really tells us to release the frontbuffer.
1768 if (current_surface_.get()) {
1769 ui::Compositor* compositor = GetCompositor();
1770 if (compositor) {
1771 // We need to wait for a commit to clear to guarantee that all we
1772 // will not issue any more GL referencing the previous surface.
1773 AddOnCommitCallbackAndDisableLocks(
1774 base::Bind(&RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor,
1775 AsWeakPtr(),
1776 current_surface_)); // Hold a ref so the texture will not
1777 // get deleted until after commit.
1779 current_surface_ = NULL;
1780 UpdateExternalTexture();
1784 bool RenderWidgetHostViewAura::HasAcceleratedSurface(
1785 const gfx::Size& desired_size) {
1786 // Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
1787 // matter what is returned here as GetBackingStore is the only caller of this
1788 // method. TODO(jbates) implement this if other Aura code needs it.
1789 return false;
1792 void RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor(
1793 scoped_refptr<ui::Texture>) {
1796 // static
1797 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult(
1798 const gfx::Size& dst_size_in_pixel,
1799 const base::Callback<void(bool, const SkBitmap&)>& callback,
1800 scoped_ptr<cc::CopyOutputResult> result) {
1801 if (result->IsEmpty() || result->size().IsEmpty()) {
1802 callback.Run(false, SkBitmap());
1803 return;
1806 if (result->HasTexture()) {
1807 PrepareTextureCopyOutputResult(dst_size_in_pixel, callback, result.Pass());
1808 return;
1811 DCHECK(result->HasBitmap());
1812 PrepareBitmapCopyOutputResult(dst_size_in_pixel, callback, result.Pass());
1815 static void CopyFromCompositingSurfaceFinished(
1816 const base::Callback<void(bool, const SkBitmap&)>& callback,
1817 scoped_ptr<cc::SingleReleaseCallback> release_callback,
1818 scoped_ptr<SkBitmap> bitmap,
1819 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
1820 bool result) {
1821 bitmap_pixels_lock.reset();
1822 release_callback->Run(0, false);
1823 callback.Run(result, *bitmap);
1826 // static
1827 void RenderWidgetHostViewAura::PrepareTextureCopyOutputResult(
1828 const gfx::Size& dst_size_in_pixel,
1829 const base::Callback<void(bool, const SkBitmap&)>& callback,
1830 scoped_ptr<cc::CopyOutputResult> result) {
1831 base::ScopedClosureRunner scoped_callback_runner(
1832 base::Bind(callback, false, SkBitmap()));
1834 DCHECK(result->HasTexture());
1835 if (!result->HasTexture())
1836 return;
1838 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
1839 bitmap->setConfig(SkBitmap::kARGB_8888_Config,
1840 dst_size_in_pixel.width(), dst_size_in_pixel.height(),
1841 0, kOpaque_SkAlphaType);
1842 if (!bitmap->allocPixels())
1843 return;
1845 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
1846 GLHelper* gl_helper = factory->GetGLHelper();
1847 if (!gl_helper)
1848 return;
1850 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
1851 new SkAutoLockPixels(*bitmap));
1852 uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
1854 cc::TextureMailbox texture_mailbox;
1855 scoped_ptr<cc::SingleReleaseCallback> release_callback;
1856 result->TakeTexture(&texture_mailbox, &release_callback);
1857 DCHECK(texture_mailbox.IsTexture());
1858 if (!texture_mailbox.IsTexture())
1859 return;
1861 ignore_result(scoped_callback_runner.Release());
1863 gl_helper->CropScaleReadbackAndCleanMailbox(
1864 texture_mailbox.name(),
1865 texture_mailbox.sync_point(),
1866 result->size(),
1867 gfx::Rect(result->size()),
1868 dst_size_in_pixel,
1869 pixels,
1870 base::Bind(&CopyFromCompositingSurfaceFinished,
1871 callback,
1872 base::Passed(&release_callback),
1873 base::Passed(&bitmap),
1874 base::Passed(&bitmap_pixels_lock)));
1877 // static
1878 void RenderWidgetHostViewAura::PrepareBitmapCopyOutputResult(
1879 const gfx::Size& dst_size_in_pixel,
1880 const base::Callback<void(bool, const SkBitmap&)>& callback,
1881 scoped_ptr<cc::CopyOutputResult> result) {
1882 DCHECK(result->HasBitmap());
1884 base::ScopedClosureRunner scoped_callback_runner(
1885 base::Bind(callback, false, SkBitmap()));
1886 if (!result->HasBitmap())
1887 return;
1889 scoped_ptr<SkBitmap> source = result->TakeBitmap();
1890 DCHECK(source);
1891 if (!source)
1892 return;
1894 ignore_result(scoped_callback_runner.Release());
1896 SkBitmap bitmap = skia::ImageOperations::Resize(
1897 *source,
1898 skia::ImageOperations::RESIZE_BEST,
1899 dst_size_in_pixel.width(),
1900 dst_size_in_pixel.height());
1901 callback.Run(true, bitmap);
1904 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinishedForVideo(
1905 base::WeakPtr<RenderWidgetHostViewAura> rwhva,
1906 const base::Callback<void(bool)>& callback,
1907 scoped_refptr<OwnedMailbox> subscriber_texture,
1908 scoped_ptr<cc::SingleReleaseCallback> release_callback,
1909 bool result) {
1910 callback.Run(result);
1912 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
1913 uint32 sync_point = gl_helper ? gl_helper->InsertSyncPoint() : 0;
1914 if (release_callback) {
1915 DCHECK(!subscriber_texture);
1916 release_callback->Run(sync_point, false);
1917 } else {
1918 // If there's no release callback, then the texture is from
1919 // idle_frame_subscriber_textures_ and we can put it back there.
1920 DCHECK(subscriber_texture);
1921 subscriber_texture->UpdateSyncPoint(sync_point);
1922 if (rwhva && rwhva->frame_subscriber_ && subscriber_texture->texture_id())
1923 rwhva->idle_frame_subscriber_textures_.push_back(subscriber_texture);
1924 subscriber_texture = NULL;
1928 // static
1929 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo(
1930 base::WeakPtr<RenderWidgetHostViewAura> rwhva,
1931 scoped_refptr<OwnedMailbox> subscriber_texture,
1932 scoped_refptr<media::VideoFrame> video_frame,
1933 const base::Callback<void(bool)>& callback,
1934 scoped_ptr<cc::CopyOutputResult> result) {
1935 base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
1937 if (!rwhva)
1938 return;
1939 if (result->IsEmpty())
1940 return;
1941 if (result->size().IsEmpty())
1942 return;
1944 // Compute the dest size we want after the letterboxing resize. Make the
1945 // coordinates and sizes even because we letterbox in YUV space
1946 // (see CopyRGBToVideoFrame). They need to be even for the UV samples to
1947 // line up correctly.
1948 // The video frame's coded_size() and the result's size() are both physical
1949 // pixels.
1950 gfx::Rect region_in_frame =
1951 media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()),
1952 result->size());
1953 region_in_frame = gfx::Rect(region_in_frame.x() & ~1,
1954 region_in_frame.y() & ~1,
1955 region_in_frame.width() & ~1,
1956 region_in_frame.height() & ~1);
1957 if (region_in_frame.IsEmpty())
1958 return;
1960 // We only handle texture readbacks for now. If the compositor is in software
1961 // mode, we could produce a software-backed VideoFrame here as well.
1962 if (!result->HasTexture()) {
1963 DCHECK(result->HasBitmap());
1964 scoped_ptr<SkBitmap> bitmap = result->TakeBitmap();
1965 // Scale the bitmap to the required size, if necessary.
1966 SkBitmap scaled_bitmap;
1967 if (result->size().width() != region_in_frame.width() ||
1968 result->size().height() != region_in_frame.height()) {
1969 skia::ImageOperations::ResizeMethod method =
1970 skia::ImageOperations::RESIZE_GOOD;
1971 scaled_bitmap = skia::ImageOperations::Resize(*bitmap.get(), method,
1972 region_in_frame.width(),
1973 region_in_frame.height());
1974 } else {
1975 scaled_bitmap = *bitmap.get();
1979 SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap);
1981 media::CopyRGBToVideoFrame(
1982 reinterpret_cast<uint8*>(scaled_bitmap.getPixels()),
1983 scaled_bitmap.rowBytes(),
1984 region_in_frame,
1985 video_frame.get());
1987 ignore_result(scoped_callback_runner.Release());
1988 callback.Run(true);
1989 return;
1992 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
1993 GLHelper* gl_helper = factory->GetGLHelper();
1994 if (!gl_helper)
1995 return;
1997 cc::TextureMailbox texture_mailbox;
1998 scoped_ptr<cc::SingleReleaseCallback> release_callback;
1999 result->TakeTexture(&texture_mailbox, &release_callback);
2000 DCHECK(texture_mailbox.IsTexture());
2001 if (!texture_mailbox.IsTexture())
2002 return;
2004 gfx::Rect result_rect(result->size());
2006 content::ReadbackYUVInterface* yuv_readback_pipeline =
2007 rwhva->yuv_readback_pipeline_.get();
2008 if (yuv_readback_pipeline == NULL ||
2009 yuv_readback_pipeline->scaler()->SrcSize() != result_rect.size() ||
2010 yuv_readback_pipeline->scaler()->SrcSubrect() != result_rect ||
2011 yuv_readback_pipeline->scaler()->DstSize() != region_in_frame.size()) {
2012 GLHelper::ScalerQuality quality = GLHelper::SCALER_QUALITY_FAST;
2013 std::string quality_switch = switches::kTabCaptureDownscaleQuality;
2014 // If we're scaling up, we can use the "best" quality.
2015 if (result_rect.size().width() < region_in_frame.size().width() &&
2016 result_rect.size().height() < region_in_frame.size().height())
2017 quality_switch = switches::kTabCaptureUpscaleQuality;
2019 std::string switch_value =
2020 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(quality_switch);
2021 if (switch_value == "fast")
2022 quality = GLHelper::SCALER_QUALITY_FAST;
2023 else if (switch_value == "good")
2024 quality = GLHelper::SCALER_QUALITY_GOOD;
2025 else if (switch_value == "best")
2026 quality = GLHelper::SCALER_QUALITY_BEST;
2028 rwhva->yuv_readback_pipeline_.reset(
2029 gl_helper->CreateReadbackPipelineYUV(quality,
2030 result_rect.size(),
2031 result_rect,
2032 video_frame->coded_size(),
2033 region_in_frame,
2034 true,
2035 true));
2036 yuv_readback_pipeline = rwhva->yuv_readback_pipeline_.get();
2039 ignore_result(scoped_callback_runner.Release());
2040 base::Callback<void(bool result)> finished_callback = base::Bind(
2041 &RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinishedForVideo,
2042 rwhva->AsWeakPtr(),
2043 callback,
2044 subscriber_texture,
2045 base::Passed(&release_callback));
2046 yuv_readback_pipeline->ReadbackYUV(
2047 texture_mailbox.name(),
2048 texture_mailbox.sync_point(),
2049 video_frame.get(),
2050 finished_callback);
2053 void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) {
2054 GetScreenInfoForWindow(results, window_->GetRootWindow() ? window_ : NULL);
2057 gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
2058 #if defined(OS_WIN)
2059 // aura::Window::GetBoundsInScreen doesn't take non-client area into
2060 // account.
2061 RECT window_rect = {0};
2063 aura::Window* top_level = window_->GetToplevelWindow();
2064 aura::WindowEventDispatcher* dispatcher = top_level->GetDispatcher();
2065 if (!dispatcher)
2066 return top_level->GetBoundsInScreen();
2067 HWND hwnd = dispatcher->host()->GetAcceleratedWidget();
2068 ::GetWindowRect(hwnd, &window_rect);
2069 gfx::Rect rect(window_rect);
2071 // Maximized windows are outdented from the work area by the frame thickness
2072 // even though this "frame" is not painted. This confuses code (and people)
2073 // that think of a maximized window as corresponding exactly to the work area.
2074 // Correct for this by subtracting the frame thickness back off.
2075 if (::IsZoomed(hwnd)) {
2076 rect.Inset(GetSystemMetrics(SM_CXSIZEFRAME),
2077 GetSystemMetrics(SM_CYSIZEFRAME));
2080 return gfx::win::ScreenToDIPRect(rect);
2081 #else
2082 return window_->GetToplevelWindow()->GetBoundsInScreen();
2083 #endif
2086 void RenderWidgetHostViewAura::GestureEventAck(int gesture_event_type,
2087 InputEventAckState ack_result) {
2088 if (touch_editing_client_)
2089 touch_editing_client_->GestureEventAck(gesture_event_type);
2092 void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
2093 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
2094 ScopedVector<ui::TouchEvent> events;
2095 if (!MakeUITouchEventsFromWebTouchEvents(touch, &events,
2096 SCREEN_COORDINATES))
2097 return;
2099 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
2100 // |dispatcher| is NULL during tests.
2101 if (!dispatcher)
2102 return;
2104 ui::EventResult result = (ack_result ==
2105 INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
2106 for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
2107 end = events.end(); iter != end; ++iter) {
2108 dispatcher->ProcessedTouchEvent((*iter), window_, result);
2112 scoped_ptr<SyntheticGestureTarget>
2113 RenderWidgetHostViewAura::CreateSyntheticGestureTarget() {
2114 return scoped_ptr<SyntheticGestureTarget>(
2115 new SyntheticGestureTargetAura(host_));
2118 void RenderWidgetHostViewAura::SetHasHorizontalScrollbar(
2119 bool has_horizontal_scrollbar) {
2120 // Not needed. Mac-only.
2123 void RenderWidgetHostViewAura::SetScrollOffsetPinning(
2124 bool is_pinned_to_left, bool is_pinned_to_right) {
2125 // Not needed. Mac-only.
2128 void RenderWidgetHostViewAura::OnAccessibilityEvents(
2129 const std::vector<AccessibilityHostMsg_EventParams>& params) {
2130 BrowserAccessibilityManager* manager =
2131 GetOrCreateBrowserAccessibilityManager();
2132 if (manager)
2133 manager->OnAccessibilityEvents(params);
2136 gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
2137 if (shared_surface_handle_.is_null()) {
2138 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
2139 shared_surface_handle_ = factory->CreateSharedSurfaceHandle();
2140 if (!shared_surface_handle_.is_null())
2141 factory->AddObserver(this);
2143 return shared_surface_handle_;
2146 bool RenderWidgetHostViewAura::LockMouse() {
2147 aura::Window* root_window = window_->GetRootWindow();
2148 if (!root_window)
2149 return false;
2151 if (mouse_locked_)
2152 return true;
2154 mouse_locked_ = true;
2155 #if !defined(OS_WIN)
2156 window_->SetCapture();
2157 #endif
2158 aura::client::CursorClient* cursor_client =
2159 aura::client::GetCursorClient(root_window);
2160 if (cursor_client) {
2161 cursor_client->HideCursor();
2162 cursor_client->LockCursor();
2165 if (ShouldMoveToCenter()) {
2166 synthetic_move_sent_ = true;
2167 window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
2169 if (aura::client::GetTooltipClient(root_window))
2170 aura::client::GetTooltipClient(root_window)->SetTooltipsEnabled(false);
2172 root_window->GetDispatcher()->host()->ConfineCursorToRootWindow();
2173 return true;
2176 void RenderWidgetHostViewAura::UnlockMouse() {
2177 aura::Window* root_window = window_->GetRootWindow();
2178 if (!mouse_locked_ || !root_window)
2179 return;
2181 mouse_locked_ = false;
2183 #if !defined(OS_WIN)
2184 window_->ReleaseCapture();
2185 #endif
2186 window_->MoveCursorTo(unlocked_mouse_position_);
2187 aura::client::CursorClient* cursor_client =
2188 aura::client::GetCursorClient(root_window);
2189 if (cursor_client) {
2190 cursor_client->UnlockCursor();
2191 cursor_client->ShowCursor();
2194 if (aura::client::GetTooltipClient(root_window))
2195 aura::client::GetTooltipClient(root_window)->SetTooltipsEnabled(true);
2197 host_->LostMouseLock();
2198 root_window->GetDispatcher()->host()->UnConfineCursor();
2201 ////////////////////////////////////////////////////////////////////////////////
2202 // RenderWidgetHostViewAura, ui::TextInputClient implementation:
2203 void RenderWidgetHostViewAura::SetCompositionText(
2204 const ui::CompositionText& composition) {
2205 if (!host_)
2206 return;
2208 // ui::CompositionUnderline should be identical to
2209 // blink::WebCompositionUnderline, so that we can do reinterpret_cast safely.
2210 COMPILE_ASSERT(sizeof(ui::CompositionUnderline) ==
2211 sizeof(blink::WebCompositionUnderline),
2212 ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
2214 // TODO(suzhe): convert both renderer_host and renderer to use
2215 // ui::CompositionText.
2216 const std::vector<blink::WebCompositionUnderline>& underlines =
2217 reinterpret_cast<const std::vector<blink::WebCompositionUnderline>&>(
2218 composition.underlines);
2220 // TODO(suzhe): due to a bug of webkit, we can't use selection range with
2221 // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
2222 host_->ImeSetComposition(composition.text, underlines,
2223 composition.selection.end(),
2224 composition.selection.end());
2226 has_composition_text_ = !composition.text.empty();
2229 void RenderWidgetHostViewAura::ConfirmCompositionText() {
2230 if (host_ && has_composition_text_) {
2231 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
2232 false);
2234 has_composition_text_ = false;
2237 void RenderWidgetHostViewAura::ClearCompositionText() {
2238 if (host_ && has_composition_text_)
2239 host_->ImeCancelComposition();
2240 has_composition_text_ = false;
2243 void RenderWidgetHostViewAura::InsertText(const base::string16& text) {
2244 DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
2245 if (host_)
2246 host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false);
2247 has_composition_text_ = false;
2250 void RenderWidgetHostViewAura::InsertChar(char16 ch, int flags) {
2251 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
2252 popup_child_host_view_->InsertChar(ch, flags);
2253 return;
2256 // Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547
2257 if (host_ && (accept_return_character_ || ch != ui::VKEY_RETURN)) {
2258 double now = ui::EventTimeForNow().InSecondsF();
2259 // Send a blink::WebInputEvent::Char event to |host_|.
2260 NativeWebKeyboardEvent webkit_event(ui::ET_KEY_PRESSED,
2261 true /* is_char */,
2263 flags,
2264 now);
2265 host_->ForwardKeyboardEvent(webkit_event);
2269 gfx::NativeWindow RenderWidgetHostViewAura::GetAttachedWindow() const {
2270 return window_;
2273 ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const {
2274 return text_input_type_;
2277 ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
2278 return text_input_mode_;
2281 bool RenderWidgetHostViewAura::CanComposeInline() const {
2282 return can_compose_inline_;
2285 gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(
2286 const gfx::Rect& rect) const {
2287 gfx::Point origin = rect.origin();
2288 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
2290 aura::Window* root_window = window_->GetRootWindow();
2291 if (!root_window)
2292 return rect;
2293 aura::client::ScreenPositionClient* screen_position_client =
2294 aura::client::GetScreenPositionClient(root_window);
2295 if (!screen_position_client)
2296 return rect;
2297 screen_position_client->ConvertPointToScreen(window_, &origin);
2298 screen_position_client->ConvertPointToScreen(window_, &end);
2299 return gfx::Rect(origin.x(),
2300 origin.y(),
2301 end.x() - origin.x(),
2302 end.y() - origin.y());
2305 gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
2306 const gfx::Rect& rect) const {
2307 gfx::Point origin = rect.origin();
2308 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
2310 aura::Window* root_window = window_->GetRootWindow();
2311 if (root_window) {
2312 aura::client::ScreenPositionClient* screen_position_client =
2313 aura::client::GetScreenPositionClient(root_window);
2314 screen_position_client->ConvertPointFromScreen(window_, &origin);
2315 screen_position_client->ConvertPointFromScreen(window_, &end);
2316 return gfx::Rect(origin.x(),
2317 origin.y(),
2318 end.x() - origin.x(),
2319 end.y() - origin.y());
2322 return rect;
2325 gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const {
2326 const gfx::Rect rect =
2327 gfx::UnionRects(selection_anchor_rect_, selection_focus_rect_);
2328 return ConvertRectToScreen(rect);
2331 bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(
2332 uint32 index,
2333 gfx::Rect* rect) const {
2334 DCHECK(rect);
2335 if (index >= composition_character_bounds_.size())
2336 return false;
2337 *rect = ConvertRectToScreen(composition_character_bounds_[index]);
2338 return true;
2341 bool RenderWidgetHostViewAura::HasCompositionText() const {
2342 return has_composition_text_;
2345 bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) const {
2346 range->set_start(selection_text_offset_);
2347 range->set_end(selection_text_offset_ + selection_text_.length());
2348 return true;
2351 bool RenderWidgetHostViewAura::GetCompositionTextRange(
2352 gfx::Range* range) const {
2353 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
2354 NOTIMPLEMENTED();
2355 return false;
2358 bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) const {
2359 range->set_start(selection_range_.start());
2360 range->set_end(selection_range_.end());
2361 return true;
2364 bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) {
2365 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
2366 NOTIMPLEMENTED();
2367 return false;
2370 bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) {
2371 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
2372 NOTIMPLEMENTED();
2373 return false;
2376 bool RenderWidgetHostViewAura::GetTextFromRange(
2377 const gfx::Range& range,
2378 base::string16* text) const {
2379 gfx::Range selection_text_range(selection_text_offset_,
2380 selection_text_offset_ + selection_text_.length());
2382 if (!selection_text_range.Contains(range)) {
2383 text->clear();
2384 return false;
2386 if (selection_text_range.EqualsIgnoringDirection(range)) {
2387 // Avoid calling substr whose performance is low.
2388 *text = selection_text_;
2389 } else {
2390 *text = selection_text_.substr(
2391 range.GetMin() - selection_text_offset_,
2392 range.length());
2394 return true;
2397 void RenderWidgetHostViewAura::OnInputMethodChanged() {
2398 if (!host_)
2399 return;
2401 if (GetInputMethod())
2402 host_->SetInputMethodActive(GetInputMethod()->IsActive());
2404 // TODO(suzhe): implement the newly added “locale” property of HTML DOM
2405 // TextEvent.
2408 bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
2409 base::i18n::TextDirection direction) {
2410 if (!host_)
2411 return false;
2412 host_->UpdateTextDirection(
2413 direction == base::i18n::RIGHT_TO_LEFT ?
2414 blink::WebTextDirectionRightToLeft :
2415 blink::WebTextDirectionLeftToRight);
2416 host_->NotifyTextDirection();
2417 return true;
2420 void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
2421 size_t before, size_t after) {
2422 if (host_)
2423 host_->ExtendSelectionAndDelete(before, after);
2426 void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
2427 gfx::Rect intersected_rect(
2428 gfx::IntersectRects(rect, window_->GetBoundsInScreen()));
2430 if (intersected_rect.IsEmpty())
2431 return;
2433 host_->ScrollFocusedEditableNodeIntoRect(
2434 ConvertRectFromScreen(intersected_rect));
2437 void RenderWidgetHostViewAura::OnCandidateWindowShown() {
2438 host_->CandidateWindowShown();
2441 void RenderWidgetHostViewAura::OnCandidateWindowUpdated() {
2442 host_->CandidateWindowUpdated();
2445 void RenderWidgetHostViewAura::OnCandidateWindowHidden() {
2446 host_->CandidateWindowHidden();
2449 ////////////////////////////////////////////////////////////////////////////////
2450 // RenderWidgetHostViewAura, gfx::DisplayObserver implementation:
2452 void RenderWidgetHostViewAura::OnDisplayBoundsChanged(
2453 const gfx::Display& display) {
2454 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
2455 if (display.id() == screen->GetDisplayNearestWindow(window_).id()) {
2456 UpdateScreenInfo(window_);
2457 current_cursor_.SetDisplayInfo(display);
2458 UpdateCursorIfOverSelf();
2462 void RenderWidgetHostViewAura::OnDisplayAdded(
2463 const gfx::Display& new_display) {
2466 void RenderWidgetHostViewAura::OnDisplayRemoved(
2467 const gfx::Display& old_display) {
2470 ////////////////////////////////////////////////////////////////////////////////
2471 // RenderWidgetHostViewAura, aura::WindowDelegate implementation:
2473 gfx::Size RenderWidgetHostViewAura::GetMinimumSize() const {
2474 return gfx::Size();
2477 gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const {
2478 return gfx::Size();
2481 void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
2482 const gfx::Rect& new_bounds) {
2483 base::AutoReset<bool> in_bounds_changed(&in_bounds_changed_, true);
2484 // We care about this only in fullscreen mode, where there is no
2485 // WebContentsViewAura. We are sized via SetSize() or SetBounds() by
2486 // WebContentsViewAura in other cases.
2487 if (is_fullscreen_)
2488 SetSize(new_bounds.size());
2491 gfx::NativeCursor RenderWidgetHostViewAura::GetCursor(const gfx::Point& point) {
2492 if (mouse_locked_)
2493 return ui::kCursorNone;
2494 return current_cursor_.GetNativeCursor();
2497 int RenderWidgetHostViewAura::GetNonClientComponent(
2498 const gfx::Point& point) const {
2499 return HTCLIENT;
2502 bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
2503 aura::Window* child,
2504 const gfx::Point& location) {
2505 return true;
2508 bool RenderWidgetHostViewAura::CanFocus() {
2509 return popup_type_ == blink::WebPopupTypeNone;
2512 void RenderWidgetHostViewAura::OnCaptureLost() {
2513 host_->LostCapture();
2514 if (touch_editing_client_)
2515 touch_editing_client_->EndTouchEditing();
2518 void RenderWidgetHostViewAura::OnPaint(gfx::Canvas* canvas) {
2519 bool has_backing_store = !!host_->GetBackingStore(false);
2520 if (has_backing_store) {
2521 paint_canvas_ = canvas;
2522 BackingStoreAura* backing_store = static_cast<BackingStoreAura*>(
2523 host_->GetBackingStore(true));
2524 paint_canvas_ = NULL;
2525 backing_store->SkiaShowRect(gfx::Point(), canvas);
2527 if (paint_observer_)
2528 paint_observer_->OnPaintComplete();
2529 ui::Compositor* compositor = GetCompositor();
2530 if (compositor) {
2531 compositor->SetLatencyInfo(software_latency_info_);
2532 software_latency_info_.Clear();
2534 } else {
2535 // For non-opaque windows, we don't draw anything, since we depend on the
2536 // canvas coming from the compositor to already be initialized as
2537 // transparent.
2538 if (window_->layer()->fills_bounds_opaquely())
2539 canvas->DrawColor(SK_ColorWHITE);
2543 void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
2544 float device_scale_factor) {
2545 if (!host_)
2546 return;
2548 BackingStoreAura* backing_store = static_cast<BackingStoreAura*>(
2549 host_->GetBackingStore(false));
2550 if (backing_store) // NULL in hardware path.
2551 backing_store->ScaleFactorChanged(device_scale_factor);
2553 UpdateScreenInfo(window_);
2555 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
2556 GetDisplayNearestWindow(window_);
2557 DCHECK_EQ(device_scale_factor, display.device_scale_factor());
2558 current_cursor_.SetDisplayInfo(display);
2561 void RenderWidgetHostViewAura::OnWindowDestroying() {
2562 #if defined(OS_WIN)
2563 HWND parent = NULL;
2564 // If the tab was hidden and it's closed, host_->is_hidden would have been
2565 // reset to false in RenderWidgetHostImpl::RendererExited.
2566 if (!window_->GetRootWindow() || host_->is_hidden()) {
2567 parent = ui::GetHiddenWindow();
2568 } else {
2569 parent = window_->GetDispatcher()->host()->GetAcceleratedWidget();
2571 LPARAM lparam = reinterpret_cast<LPARAM>(this);
2572 EnumChildWindows(parent, WindowDestroyingCallback, lparam);
2573 #endif
2575 // Make sure that the input method no longer references to this object before
2576 // this object is removed from the root window (i.e. this object loses access
2577 // to the input method).
2578 ui::InputMethod* input_method = GetInputMethod();
2579 if (input_method)
2580 input_method->DetachTextInputClient(this);
2583 void RenderWidgetHostViewAura::OnWindowDestroyed() {
2584 host_->ViewDestroyed();
2585 delete this;
2588 void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible) {
2591 bool RenderWidgetHostViewAura::HasHitTestMask() const {
2592 return false;
2595 void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
2598 void RenderWidgetHostViewAura::DidRecreateLayer(ui::Layer *old_layer,
2599 ui::Layer *new_layer) {
2600 float mailbox_scale_factor;
2601 cc::TextureMailbox old_mailbox =
2602 old_layer->GetTextureMailbox(&mailbox_scale_factor);
2603 scoped_refptr<ui::Texture> old_texture = old_layer->external_texture();
2604 // The new_layer is the one that will be used by our Window, so that's the one
2605 // that should keep our texture. old_layer will be returned to the
2606 // RecreateLayer caller, and should have a copy.
2607 if (old_texture.get()) {
2608 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
2609 GLHelper* gl_helper = factory->GetGLHelper();
2610 scoped_refptr<ui::Texture> new_texture;
2611 if (host_->is_accelerated_compositing_active() &&
2612 gl_helper && current_surface_.get()) {
2613 blink::WebGLId texture_id =
2614 gl_helper->CopyTexture(current_surface_->PrepareTexture(),
2615 current_surface_->size());
2616 if (texture_id) {
2617 new_texture = factory->CreateOwnedTexture(
2618 current_surface_->size(),
2619 current_surface_->device_scale_factor(), texture_id);
2622 if (new_texture.get())
2623 old_layer->SetExternalTexture(new_texture.get());
2624 else
2625 old_layer->SetShowPaintedContent();
2626 new_layer->SetExternalTexture(old_texture.get());
2627 } else if (old_mailbox.IsSharedMemory()) {
2628 base::SharedMemory* old_buffer = old_mailbox.shared_memory();
2629 const size_t size = old_mailbox.shared_memory_size_in_bytes();
2631 scoped_ptr<base::SharedMemory> new_buffer(new base::SharedMemory);
2632 new_buffer->CreateAndMapAnonymous(size);
2634 if (old_buffer->memory() && new_buffer->memory()) {
2635 memcpy(new_buffer->memory(), old_buffer->memory(), size);
2636 base::SharedMemory* new_buffer_raw_ptr = new_buffer.get();
2637 scoped_ptr<cc::SingleReleaseCallback> callback =
2638 cc::SingleReleaseCallback::Create(base::Bind(MailboxReleaseCallback,
2639 Passed(&new_buffer)));
2640 cc::TextureMailbox new_mailbox(new_buffer_raw_ptr,
2641 old_mailbox.shared_memory_size());
2642 new_layer->SetTextureMailbox(new_mailbox,
2643 callback.Pass(),
2644 mailbox_scale_factor);
2646 } else if (frame_provider_.get()) {
2647 new_layer->SetShowDelegatedContent(frame_provider_.get(),
2648 current_frame_size_);
2652 ////////////////////////////////////////////////////////////////////////////////
2653 // RenderWidgetHostViewAura, ui::EventHandler implementation:
2655 void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
2656 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent");
2657 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2658 return;
2660 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
2661 popup_child_host_view_->OnKeyEvent(event);
2662 if (event->handled())
2663 return;
2666 // We need to handle the Escape key for Pepper Flash.
2667 if (is_fullscreen_ && event->key_code() == ui::VKEY_ESCAPE) {
2668 // Focus the window we were created from.
2669 if (host_tracker_.get() && !host_tracker_->windows().empty()) {
2670 aura::Window* host = *(host_tracker_->windows().begin());
2671 aura::client::FocusClient* client = aura::client::GetFocusClient(host);
2672 if (client) {
2673 // Calling host->Focus() may delete |this|. We create a local observer
2674 // for that. In that case we exit without further access to any members.
2675 aura::WindowTracker tracker;
2676 aura::Window* window = window_;
2677 tracker.Add(window);
2678 host->Focus();
2679 if (!tracker.Contains(window)) {
2680 event->SetHandled();
2681 return;
2685 if (!in_shutdown_) {
2686 in_shutdown_ = true;
2687 host_->Shutdown();
2689 } else {
2690 // Accept return key character events between its press and release events.
2691 if (event->key_code() == ui::VKEY_RETURN)
2692 accept_return_character_ = event->type() == ui::ET_KEY_PRESSED;
2694 // We don't have to communicate with an input method here.
2695 if (!event->HasNativeEvent()) {
2696 NativeWebKeyboardEvent webkit_event(
2697 event->type(),
2698 event->is_char(),
2699 event->is_char() ? event->GetCharacter() : event->key_code(),
2700 event->flags(),
2701 ui::EventTimeForNow().InSecondsF());
2702 host_->ForwardKeyboardEvent(webkit_event);
2703 } else {
2704 NativeWebKeyboardEvent webkit_event(event);
2705 host_->ForwardKeyboardEvent(webkit_event);
2708 event->SetHandled();
2711 void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
2712 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
2714 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2715 return;
2717 if (mouse_locked_) {
2718 aura::client::CursorClient* cursor_client =
2719 aura::client::GetCursorClient(window_->GetRootWindow());
2720 DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
2722 if (event->type() == ui::ET_MOUSEWHEEL) {
2723 blink::WebMouseWheelEvent mouse_wheel_event =
2724 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
2725 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
2726 host_->ForwardWheelEvent(mouse_wheel_event);
2727 return;
2730 gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
2732 // If we receive non client mouse messages while we are in the locked state
2733 // it probably means that the mouse left the borders of our window and
2734 // needs to be moved back to the center.
2735 if (event->flags() & ui::EF_IS_NON_CLIENT) {
2736 synthetic_move_sent_ = true;
2737 window_->MoveCursorTo(center);
2738 return;
2741 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
2743 bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED ||
2744 event->type() == ui::ET_MOUSE_DRAGGED) &&
2745 mouse_event.x == center.x() && mouse_event.y == center.y();
2747 ModifyEventMovementAndCoords(&mouse_event);
2749 bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
2750 if (should_not_forward) {
2751 synthetic_move_sent_ = false;
2752 } else {
2753 // Check if the mouse has reached the border and needs to be centered.
2754 if (ShouldMoveToCenter()) {
2755 synthetic_move_sent_ = true;
2756 window_->MoveCursorTo(center);
2758 // Forward event to renderer.
2759 if (CanRendererHandleEvent(event) &&
2760 !(event->flags() & ui::EF_FROM_TOUCH)) {
2761 host_->ForwardMouseEvent(mouse_event);
2762 // Ensure that we get keyboard focus on mouse down as a plugin window
2763 // may have grabbed keyboard focus.
2764 if (event->type() == ui::ET_MOUSE_PRESSED)
2765 SetKeyboardFocus();
2768 return;
2771 // As the overscroll is handled during scroll events from the trackpad, the
2772 // RWHVA window is transformed by the overscroll controller. This transform
2773 // triggers a synthetic mouse-move event to be generated (by the aura
2774 // RootWindow). But this event interferes with the overscroll gesture. So,
2775 // ignore such synthetic mouse-move events if an overscroll gesture is in
2776 // progress.
2777 if (host_->overscroll_controller() &&
2778 host_->overscroll_controller()->overscroll_mode() != OVERSCROLL_NONE &&
2779 event->flags() & ui::EF_IS_SYNTHESIZED &&
2780 (event->type() == ui::ET_MOUSE_ENTERED ||
2781 event->type() == ui::ET_MOUSE_EXITED ||
2782 event->type() == ui::ET_MOUSE_MOVED)) {
2783 event->StopPropagation();
2784 return;
2787 if (event->type() == ui::ET_MOUSEWHEEL) {
2788 #if defined(OS_WIN)
2789 // We get mouse wheel/scroll messages even if we are not in the foreground.
2790 // So here we check if we have any owned popup windows in the foreground and
2791 // dismiss them.
2792 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
2793 if (dispatcher) {
2794 HWND parent = dispatcher->host()->GetAcceleratedWidget();
2795 HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
2796 EnumThreadWindows(GetCurrentThreadId(),
2797 DismissOwnedPopups,
2798 reinterpret_cast<LPARAM>(toplevel_hwnd));
2800 #endif
2801 blink::WebMouseWheelEvent mouse_wheel_event =
2802 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
2803 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
2804 host_->ForwardWheelEvent(mouse_wheel_event);
2805 } else if (CanRendererHandleEvent(event) &&
2806 !(event->flags() & ui::EF_FROM_TOUCH)) {
2807 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
2808 ModifyEventMovementAndCoords(&mouse_event);
2809 host_->ForwardMouseEvent(mouse_event);
2810 // Ensure that we get keyboard focus on mouse down as a plugin window may
2811 // have grabbed keyboard focus.
2812 if (event->type() == ui::ET_MOUSE_PRESSED)
2813 SetKeyboardFocus();
2816 switch (event->type()) {
2817 case ui::ET_MOUSE_PRESSED:
2818 window_->SetCapture();
2819 // Confirm existing composition text on mouse click events, to make sure
2820 // the input caret won't be moved with an ongoing composition text.
2821 FinishImeCompositionSession();
2822 break;
2823 case ui::ET_MOUSE_RELEASED:
2824 window_->ReleaseCapture();
2825 break;
2826 default:
2827 break;
2830 // Needed to propagate mouse event to native_tab_contents_view_aura.
2831 // TODO(pkotwicz): Find a better way of doing this.
2832 // In fullscreen mode which is typically used by flash, don't forward
2833 // the mouse events to the parent. The renderer and the plugin process
2834 // handle these events.
2835 if (!is_fullscreen_ && window_->parent()->delegate() &&
2836 !(event->flags() & ui::EF_FROM_TOUCH))
2837 window_->parent()->delegate()->OnMouseEvent(event);
2839 if (!IsXButtonUpEvent(event))
2840 event->SetHandled();
2843 void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
2844 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
2845 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2846 return;
2848 if (event->type() == ui::ET_SCROLL) {
2849 if (event->finger_count() != 2)
2850 return;
2851 blink::WebGestureEvent gesture_event =
2852 MakeWebGestureEventFlingCancel();
2853 host_->ForwardGestureEvent(gesture_event);
2854 blink::WebMouseWheelEvent mouse_wheel_event =
2855 MakeWebMouseWheelEvent(event);
2856 host_->ForwardWheelEvent(mouse_wheel_event);
2857 RecordAction(UserMetricsAction("TrackpadScroll"));
2858 } else if (event->type() == ui::ET_SCROLL_FLING_START ||
2859 event->type() == ui::ET_SCROLL_FLING_CANCEL) {
2860 blink::WebGestureEvent gesture_event =
2861 MakeWebGestureEvent(event);
2862 host_->ForwardGestureEvent(gesture_event);
2863 if (event->type() == ui::ET_SCROLL_FLING_START)
2864 RecordAction(UserMetricsAction("TrackpadScrollFling"));
2867 event->SetHandled();
2870 void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
2871 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent");
2872 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2873 return;
2875 // Update the touch event first.
2876 blink::WebTouchPoint* point = UpdateWebTouchEventFromUIEvent(*event,
2877 &touch_event_);
2879 // Forward the touch event only if a touch point was updated, and there's a
2880 // touch-event handler in the page, and no other touch-event is in the queue.
2881 // It is important to always consume the event if there is a touch-event
2882 // handler in the page, or some touch-event is already in the queue, even if
2883 // no point has been updated, to make sure that this event does not get
2884 // processed by the gesture recognizer before the events in the queue.
2885 if (host_->ShouldForwardTouchEvent())
2886 event->StopPropagation();
2888 if (point) {
2889 if (host_->ShouldForwardTouchEvent())
2890 host_->ForwardTouchEventWithLatencyInfo(touch_event_, *event->latency());
2891 UpdateWebTouchEventAfterDispatch(&touch_event_, point);
2895 void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
2896 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent");
2897 // Pinch gestures are currently disabled by default. See crbug.com/128477.
2898 if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN ||
2899 event->type() == ui::ET_GESTURE_PINCH_UPDATE ||
2900 event->type() == ui::ET_GESTURE_PINCH_END) && !ShouldSendPinchGesture()) {
2901 event->SetHandled();
2902 return;
2905 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2906 return;
2908 RenderViewHostDelegate* delegate = NULL;
2909 if (popup_type_ == blink::WebPopupTypeNone && !is_fullscreen_)
2910 delegate = RenderViewHost::From(host_)->GetDelegate();
2912 if (delegate && event->type() == ui::ET_GESTURE_BEGIN &&
2913 event->details().touch_points() == 1) {
2914 delegate->HandleGestureBegin();
2917 blink::WebGestureEvent gesture = MakeWebGestureEvent(event);
2918 if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
2919 // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
2920 // event to stop any in-progress flings.
2921 blink::WebGestureEvent fling_cancel = gesture;
2922 fling_cancel.type = blink::WebInputEvent::GestureFlingCancel;
2923 fling_cancel.sourceDevice = blink::WebGestureEvent::Touchscreen;
2924 host_->ForwardGestureEvent(fling_cancel);
2927 if (gesture.type != blink::WebInputEvent::Undefined) {
2928 host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
2930 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
2931 event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
2932 event->type() == ui::ET_GESTURE_SCROLL_END) {
2933 RecordAction(UserMetricsAction("TouchscreenScroll"));
2934 } else if (event->type() == ui::ET_SCROLL_FLING_START) {
2935 RecordAction(UserMetricsAction("TouchscreenScrollFling"));
2939 if (delegate && event->type() == ui::ET_GESTURE_END &&
2940 event->details().touch_points() == 1) {
2941 delegate->HandleGestureEnd();
2944 // If a gesture is not processed by the webpage, then WebKit processes it
2945 // (e.g. generates synthetic mouse events).
2946 event->SetHandled();
2949 ////////////////////////////////////////////////////////////////////////////////
2950 // RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation:
2952 bool RenderWidgetHostViewAura::ShouldActivate() const {
2953 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
2954 if (!dispatcher)
2955 return true;
2956 const ui::Event* event = dispatcher->current_event();
2957 if (!event)
2958 return true;
2959 return is_fullscreen_;
2962 ////////////////////////////////////////////////////////////////////////////////
2963 // RenderWidgetHostViewAura,
2964 // aura::client::ActivationChangeObserver implementation:
2966 void RenderWidgetHostViewAura::OnWindowActivated(aura::Window* gained_active,
2967 aura::Window* lost_active) {
2968 DCHECK(window_ == gained_active || window_ == lost_active);
2969 if (window_ == gained_active) {
2970 const ui::Event* event = window_->GetDispatcher()->current_event();
2971 if (event && PointerEventActivates(*event))
2972 host_->OnPointerEventActivate();
2976 ////////////////////////////////////////////////////////////////////////////////
2977 // RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation:
2979 void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible) {
2980 NotifyRendererOfCursorVisibilityState(is_visible);
2983 ////////////////////////////////////////////////////////////////////////////////
2984 // RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation:
2986 void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
2987 aura::Window* lost_focus) {
2988 DCHECK(window_ == gained_focus || window_ == lost_focus);
2989 if (window_ == gained_focus) {
2990 // We need to honor input bypass if the associated tab is does not want
2991 // input. This gives the current focused window a chance to be the text
2992 // input client and handle events.
2993 if (host_->ignore_input_events())
2994 return;
2996 host_->GotFocus();
2997 host_->SetActive(true);
2999 ui::InputMethod* input_method = GetInputMethod();
3000 if (input_method) {
3001 // Ask the system-wide IME to send all TextInputClient messages to |this|
3002 // object.
3003 input_method->SetFocusedTextInputClient(this);
3004 host_->SetInputMethodActive(input_method->IsActive());
3006 // Often the application can set focus to the view in response to a key
3007 // down. However the following char event shouldn't be sent to the web
3008 // page.
3009 host_->SuppressNextCharEvents();
3010 } else {
3011 host_->SetInputMethodActive(false);
3013 } else if (window_ == lost_focus) {
3014 host_->SetActive(false);
3015 host_->Blur();
3017 DetachFromInputMethod();
3018 host_->SetInputMethodActive(false);
3020 if (touch_editing_client_)
3021 touch_editing_client_->EndTouchEditing();
3023 // If we lose the focus while fullscreen, close the window; Pepper Flash
3024 // won't do it for us (unlike NPAPI Flash). However, we do not close the
3025 // window if we lose the focus to a window on another display.
3026 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
3027 bool focusing_other_display =
3028 gained_focus && screen->GetNumDisplays() > 1 &&
3029 (screen->GetDisplayNearestWindow(window_).id() !=
3030 screen->GetDisplayNearestWindow(gained_focus).id());
3031 if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) {
3032 #if defined(OS_WIN)
3033 // On Windows, if we are switching to a non Aura Window on a different
3034 // screen we should not close the fullscreen window.
3035 if (!gained_focus) {
3036 POINT point = {0};
3037 ::GetCursorPos(&point);
3038 if (screen->GetDisplayNearestWindow(window_).id() !=
3039 screen->GetDisplayNearestPoint(gfx::Point(point)).id())
3040 return;
3042 #endif
3043 in_shutdown_ = true;
3044 host_->Shutdown();
3049 ////////////////////////////////////////////////////////////////////////////////
3050 // RenderWidgetHostViewAura, aura::RootWindowObserver implementation:
3052 void RenderWidgetHostViewAura::OnRootWindowHostMoved(
3053 const aura::RootWindow* root,
3054 const gfx::Point& new_origin) {
3055 TRACE_EVENT1("ui", "RenderWidgetHostViewAura::OnRootWindowHostMoved",
3056 "new_origin", new_origin.ToString());
3058 UpdateScreenInfo(window_);
3061 ////////////////////////////////////////////////////////////////////////////////
3062 // RenderWidgetHostViewAura, SoftwareFrameManagerClient implementation:
3064 void RenderWidgetHostViewAura::SoftwareFrameWasFreed(
3065 uint32 output_surface_id, unsigned frame_id) {
3066 ReleaseSoftwareFrame(output_surface_id, frame_id);
3069 void RenderWidgetHostViewAura::ReleaseReferencesToSoftwareFrame() {
3070 ui::Compositor* compositor = GetCompositor();
3071 if (compositor) {
3072 AddOnCommitCallbackAndDisableLocks(base::Bind(
3073 &RenderWidgetHostViewAura::SendReclaimSoftwareFrames, AsWeakPtr()));
3075 UpdateExternalTexture();
3078 ////////////////////////////////////////////////////////////////////////////////
3079 // RenderWidgetHostViewAura, ui::CompositorObserver implementation:
3081 void RenderWidgetHostViewAura::OnCompositingDidCommit(
3082 ui::Compositor* compositor) {
3083 if (can_lock_compositor_ == NO_PENDING_COMMIT) {
3084 can_lock_compositor_ = YES;
3085 if (resize_lock_.get() && resize_lock_->GrabDeferredLock())
3086 can_lock_compositor_ = YES_DID_LOCK;
3088 RunOnCommitCallbacks();
3089 if (resize_lock_ && resize_lock_->expected_size() == current_frame_size_) {
3090 resize_lock_.reset();
3091 host_->WasResized();
3092 // We may have had a resize while we had the lock (e.g. if the lock expired,
3093 // or if the UI still gave us some resizes), so make sure we grab a new lock
3094 // if necessary.
3095 MaybeCreateResizeLock();
3099 void RenderWidgetHostViewAura::OnCompositingStarted(
3100 ui::Compositor* compositor, base::TimeTicks start_time) {
3101 last_draw_ended_ = start_time;
3104 void RenderWidgetHostViewAura::OnCompositingEnded(
3105 ui::Compositor* compositor) {
3106 if (paint_observer_)
3107 paint_observer_->OnCompositingComplete();
3110 void RenderWidgetHostViewAura::OnCompositingAborted(
3111 ui::Compositor* compositor) {
3114 void RenderWidgetHostViewAura::OnCompositingLockStateChanged(
3115 ui::Compositor* compositor) {
3116 // A compositor lock that is part of a resize lock timed out. We
3117 // should display a renderer frame.
3118 if (!compositor->IsLocked() && can_lock_compositor_ == YES_DID_LOCK) {
3119 can_lock_compositor_ = NO_PENDING_RENDERER_FRAME;
3123 void RenderWidgetHostViewAura::OnUpdateVSyncParameters(
3124 ui::Compositor* compositor,
3125 base::TimeTicks timebase,
3126 base::TimeDelta interval) {
3127 if (IsShowing()) {
3128 if (IsDeadlineSchedulingEnabled()) {
3129 // The deadline scheduler has logic to stagger the draws of the
3130 // Renderer and Browser built-in, so send it an accurate timebase.
3131 host_->UpdateVSyncParameters(timebase, interval);
3132 } else if (!last_draw_ended_.is_null()) {
3133 // For the non-deadline scheduler, we send the Renderer an offset
3134 // vsync timebase to avoid its draws racing the Browser's draws.
3135 host_->UpdateVSyncParameters(last_draw_ended_, interval);
3140 ////////////////////////////////////////////////////////////////////////////////
3141 // RenderWidgetHostViewAura, BrowserAccessibilityDelegate implementation:
3143 void RenderWidgetHostViewAura::SetAccessibilityFocus(int acc_obj_id) {
3144 if (!host_)
3145 return;
3147 host_->AccessibilitySetFocus(acc_obj_id);
3150 void RenderWidgetHostViewAura::AccessibilityDoDefaultAction(int acc_obj_id) {
3151 if (!host_)
3152 return;
3154 host_->AccessibilityDoDefaultAction(acc_obj_id);
3157 void RenderWidgetHostViewAura::AccessibilityScrollToMakeVisible(
3158 int acc_obj_id, gfx::Rect subfocus) {
3159 if (!host_)
3160 return;
3162 host_->AccessibilityScrollToMakeVisible(acc_obj_id, subfocus);
3165 void RenderWidgetHostViewAura::AccessibilityScrollToPoint(
3166 int acc_obj_id, gfx::Point point) {
3167 if (!host_)
3168 return;
3170 host_->AccessibilityScrollToPoint(acc_obj_id, point);
3173 void RenderWidgetHostViewAura::AccessibilitySetTextSelection(
3174 int acc_obj_id, int start_offset, int end_offset) {
3175 if (!host_)
3176 return;
3178 host_->AccessibilitySetTextSelection(
3179 acc_obj_id, start_offset, end_offset);
3182 gfx::Point RenderWidgetHostViewAura::GetLastTouchEventLocation() const {
3183 // Only needed for Win 8 non-aura.
3184 return gfx::Point();
3187 void RenderWidgetHostViewAura::FatalAccessibilityTreeError() {
3188 host_->FatalAccessibilityTreeError();
3189 SetBrowserAccessibilityManager(NULL);
3192 ////////////////////////////////////////////////////////////////////////////////
3193 // RenderWidgetHostViewAura, ImageTransportFactoryObserver implementation:
3195 void RenderWidgetHostViewAura::OnLostResources() {
3196 current_surface_ = NULL;
3197 UpdateExternalTexture();
3199 idle_frame_subscriber_textures_.clear();
3201 // Make sure all ImageTransportClients are deleted now that the context those
3202 // are using is becoming invalid. This sends pending ACKs and needs to happen
3203 // after calling UpdateExternalTexture() which syncs with the impl thread.
3204 RunOnCommitCallbacks();
3206 DCHECK(!shared_surface_handle_.is_null());
3207 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
3208 factory->DestroySharedSurfaceHandle(shared_surface_handle_);
3209 shared_surface_handle_ = factory->CreateSharedSurfaceHandle();
3210 host_->CompositingSurfaceUpdated();
3211 host_->ScheduleComposite();
3214 ////////////////////////////////////////////////////////////////////////////////
3215 // RenderWidgetHostViewAura, private:
3217 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
3218 if (paint_observer_)
3219 paint_observer_->OnViewDestroyed();
3220 if (touch_editing_client_)
3221 touch_editing_client_->OnViewDestroyed();
3222 if (!shared_surface_handle_.is_null()) {
3223 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
3224 factory->DestroySharedSurfaceHandle(shared_surface_handle_);
3225 factory->RemoveObserver(this);
3227 window_observer_.reset();
3228 if (window_->GetDispatcher())
3229 window_->GetDispatcher()->RemoveRootWindowObserver(this);
3230 UnlockMouse();
3231 if (popup_parent_host_view_) {
3232 DCHECK(popup_parent_host_view_->popup_child_host_view_ == NULL ||
3233 popup_parent_host_view_->popup_child_host_view_ == this);
3234 popup_parent_host_view_->popup_child_host_view_ = NULL;
3236 if (popup_child_host_view_) {
3237 DCHECK(popup_child_host_view_->popup_parent_host_view_ == NULL ||
3238 popup_child_host_view_->popup_parent_host_view_ == this);
3239 popup_child_host_view_->popup_parent_host_view_ = NULL;
3241 aura::client::SetTooltipText(window_, NULL);
3242 gfx::Screen::GetScreenFor(window_)->RemoveObserver(this);
3244 // This call is usually no-op since |this| object is already removed from the
3245 // Aura root window and we don't have a way to get an input method object
3246 // associated with the window, but just in case.
3247 DetachFromInputMethod();
3249 if (resource_collection_.get())
3250 resource_collection_->SetClient(NULL);
3252 #if defined(OS_WIN)
3253 if (::IsWindow(plugin_parent_window_))
3254 ::DestroyWindow(plugin_parent_window_);
3255 #endif
3258 void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
3259 const gfx::Point screen_point =
3260 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
3261 aura::Window* root_window = window_->GetRootWindow();
3262 if (!root_window)
3263 return;
3265 gfx::Rect screen_rect = GetViewBounds();
3266 gfx::Point local_point = screen_point;
3267 local_point.Offset(-screen_rect.x(), -screen_rect.y());
3269 #if defined(OS_WIN)
3270 // If there's another toplevel window above us at this point (for example a
3271 // menu), we don't want to update the cursor.
3272 POINT windows_point = { screen_point.x(), screen_point.y() };
3273 aura::WindowEventDispatcher* dispatcher = root_window->GetDispatcher();
3274 if (dispatcher->host()->GetAcceleratedWidget() !=
3275 ::WindowFromPoint(windows_point))
3276 return;
3277 #endif
3278 if (root_window->GetEventHandlerForPoint(local_point) != window_)
3279 return;
3281 gfx::NativeCursor cursor = current_cursor_.GetNativeCursor();
3282 // Do not show loading cursor when the cursor is currently hidden.
3283 if (is_loading_ && cursor != ui::kCursorNone)
3284 cursor = ui::kCursorPointer;
3286 aura::client::CursorClient* cursor_client =
3287 aura::client::GetCursorClient(root_window);
3288 if (cursor_client) {
3289 cursor_client->SetCursor(cursor);
3293 ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
3294 aura::Window* root_window = window_->GetRootWindow();
3295 if (!root_window)
3296 return NULL;
3297 return root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
3300 bool RenderWidgetHostViewAura::NeedsInputGrab() {
3301 return popup_type_ == blink::WebPopupTypeSelect;
3304 void RenderWidgetHostViewAura::FinishImeCompositionSession() {
3305 if (!has_composition_text_)
3306 return;
3307 if (host_) {
3308 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
3309 false);
3311 ImeCancelComposition();
3314 void RenderWidgetHostViewAura::ModifyEventMovementAndCoords(
3315 blink::WebMouseEvent* event) {
3316 // If the mouse has just entered, we must report zero movementX/Y. Hence we
3317 // reset any global_mouse_position set previously.
3318 if (event->type == blink::WebInputEvent::MouseEnter ||
3319 event->type == blink::WebInputEvent::MouseLeave)
3320 global_mouse_position_.SetPoint(event->globalX, event->globalY);
3322 // Movement is computed by taking the difference of the new cursor position
3323 // and the previous. Under mouse lock the cursor will be warped back to the
3324 // center so that we are not limited by clipping boundaries.
3325 // We do not measure movement as the delta from cursor to center because
3326 // we may receive more mouse movement events before our warp has taken
3327 // effect.
3328 event->movementX = event->globalX - global_mouse_position_.x();
3329 event->movementY = event->globalY - global_mouse_position_.y();
3331 global_mouse_position_.SetPoint(event->globalX, event->globalY);
3333 // Under mouse lock, coordinates of mouse are locked to what they were when
3334 // mouse lock was entered.
3335 if (mouse_locked_) {
3336 event->x = unlocked_mouse_position_.x();
3337 event->y = unlocked_mouse_position_.y();
3338 event->windowX = unlocked_mouse_position_.x();
3339 event->windowY = unlocked_mouse_position_.y();
3340 event->globalX = unlocked_global_mouse_position_.x();
3341 event->globalY = unlocked_global_mouse_position_.y();
3342 } else {
3343 unlocked_mouse_position_.SetPoint(event->windowX, event->windowY);
3344 unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY);
3348 void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
3349 bool is_visible) {
3350 if (host_->is_hidden() ||
3351 (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) ||
3352 (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible))
3353 return;
3355 cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE;
3356 host_->SendCursorVisibilityState(is_visible);
3359 void RenderWidgetHostViewAura::SchedulePaintIfNotInClip(
3360 const gfx::Rect& rect,
3361 const gfx::Rect& clip) {
3362 if (!clip.IsEmpty()) {
3363 gfx::Rect to_paint = gfx::SubtractRects(rect, clip);
3364 if (!to_paint.IsEmpty())
3365 window_->SchedulePaintInRect(to_paint);
3366 } else {
3367 window_->SchedulePaintInRect(rect);
3371 bool RenderWidgetHostViewAura::ShouldMoveToCenter() {
3372 gfx::Rect rect = window_->bounds();
3373 rect = ConvertRectToScreen(rect);
3374 int border_x = rect.width() * kMouseLockBorderPercentage / 100;
3375 int border_y = rect.height() * kMouseLockBorderPercentage / 100;
3377 return global_mouse_position_.x() < rect.x() + border_x ||
3378 global_mouse_position_.x() > rect.right() - border_x ||
3379 global_mouse_position_.y() < rect.y() + border_y ||
3380 global_mouse_position_.y() > rect.bottom() - border_y;
3383 void RenderWidgetHostViewAura::RunOnCommitCallbacks() {
3384 for (std::vector<base::Closure>::const_iterator
3385 it = on_compositing_did_commit_callbacks_.begin();
3386 it != on_compositing_did_commit_callbacks_.end(); ++it) {
3387 it->Run();
3389 on_compositing_did_commit_callbacks_.clear();
3392 void RenderWidgetHostViewAura::AddOnCommitCallbackAndDisableLocks(
3393 const base::Closure& callback) {
3394 ui::Compositor* compositor = GetCompositor();
3395 DCHECK(compositor);
3397 if (!compositor->HasObserver(this))
3398 compositor->AddObserver(this);
3400 can_lock_compositor_ = NO_PENDING_COMMIT;
3401 on_compositing_did_commit_callbacks_.push_back(callback);
3404 void RenderWidgetHostViewAura::AddedToRootWindow() {
3405 window_->GetDispatcher()->AddRootWindowObserver(this);
3406 host_->ParentChanged(GetNativeViewId());
3407 UpdateScreenInfo(window_);
3408 if (popup_type_ != blink::WebPopupTypeNone)
3409 event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
3411 aura::client::CursorClient* cursor_client =
3412 aura::client::GetCursorClient(window_->GetRootWindow());
3413 if (cursor_client) {
3414 cursor_client->AddObserver(this);
3415 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
3417 if (current_surface_.get())
3418 UpdateExternalTexture();
3421 void RenderWidgetHostViewAura::RemovingFromRootWindow() {
3422 aura::client::CursorClient* cursor_client =
3423 aura::client::GetCursorClient(window_->GetRootWindow());
3424 if (cursor_client)
3425 cursor_client->RemoveObserver(this);
3427 DetachFromInputMethod();
3429 event_filter_for_popup_exit_.reset();
3430 window_->GetDispatcher()->RemoveRootWindowObserver(this);
3431 host_->ParentChanged(0);
3432 ui::Compositor* compositor = GetCompositor();
3433 if (current_surface_.get()) {
3434 // We can't get notification for commits after this point, which would
3435 // guarantee that the compositor isn't using an old texture any more, so
3436 // instead we force the layer to stop using any external resources which
3437 // synchronizes with the compositor thread, and makes it safe to run the
3438 // callback.
3439 window_->layer()->SetShowPaintedContent();
3441 RunOnCommitCallbacks();
3442 resize_lock_.reset();
3443 host_->WasResized();
3444 if (compositor && compositor->HasObserver(this))
3445 compositor->RemoveObserver(this);
3448 ui::Compositor* RenderWidgetHostViewAura::GetCompositor() const {
3449 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
3450 return dispatcher ? dispatcher->compositor() : NULL;
3453 void RenderWidgetHostViewAura::DetachFromInputMethod() {
3454 ui::InputMethod* input_method = GetInputMethod();
3455 if (input_method && input_method->GetTextInputClient() == this)
3456 input_method->SetFocusedTextInputClient(NULL);
3459 ////////////////////////////////////////////////////////////////////////////////
3460 // RenderWidgetHostView, public:
3462 // static
3463 RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
3464 RenderWidgetHost* widget) {
3465 return new RenderWidgetHostViewAura(widget);
3468 // static
3469 void RenderWidgetHostViewPort::GetDefaultScreenInfo(WebScreenInfo* results) {
3470 GetScreenInfoForWindow(results, NULL);
3473 } // namespace content