1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
7 #include "base/auto_reset.h"
8 #include "base/basictypes.h"
10 #include "base/callback_helpers.h"
11 #include "base/command_line.h"
12 #include "base/debug/trace_event.h"
13 #include "base/logging.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "cc/layers/delegated_frame_provider.h"
17 #include "cc/output/compositor_frame.h"
18 #include "cc/output/compositor_frame_ack.h"
19 #include "cc/output/copy_output_request.h"
20 #include "cc/output/copy_output_result.h"
21 #include "cc/resources/texture_mailbox.h"
22 #include "cc/trees/layer_tree_settings.h"
23 #include "content/browser/accessibility/browser_accessibility_manager.h"
24 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
25 #include "content/browser/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"
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"
90 using gfx::RectToSkIRect
;
91 using gfx::SkIRectToRect
;
93 using blink::WebScreenInfo
;
94 using blink::WebTouchEvent
;
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;
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
);
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());
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
);
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();
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
) {
186 if (i
== params
->geometry
->end()) {
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
);
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);
225 void UpdateWebTouchEventAfterDispatch(blink::WebTouchEvent
* event
,
226 blink::WebTouchPoint
* point
) {
227 if (point
->state
!= blink::WebTouchPoint::StateReleased
&&
228 point
->state
!= blink::WebTouchPoint::StateCancelled
)
230 --event
->touchesLength
;
231 for (unsigned i
= point
- event
->touches
;
232 i
< event
->touchesLength
;
234 event
->touches
[i
] = event
->touches
[i
+ 1];
238 bool CanRendererHandleEvent(const ui::MouseEvent
* event
) {
239 if (event
->type() == ui::ET_MOUSE_CAPTURE_CHANGED
)
243 // Renderer cannot handle WM_XBUTTON or NC events.
244 switch (event
->native_event().message
) {
247 case WM_XBUTTONDBLCLK
:
248 case WM_NCMOUSELEAVE
:
250 case WM_NCXBUTTONDOWN
:
252 case WM_NCXBUTTONDBLCLK
:
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
) {
265 switch (event
->native_event().message
) {
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.
282 results
->depthPerComponent
= 8;
283 results
->deviceScaleFactor
= display
.device_scale_factor();
286 bool ShouldSendPinchGesture() {
288 if (base::win::GetVersion() >= base::win::VERSION_WIN8
)
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
)
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;
310 // Swap ack for the renderer when kCompositeToMailbox is enabled.
311 void SendCompositorFrameAck(
313 uint32 output_surface_id
,
314 int renderer_host_id
,
315 const gpu::Mailbox
& received_mailbox
,
316 const gfx::Size
& received_size
,
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
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(
344 const std::string
& received_mailbox
,
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();
353 content::ImageTransportFactory::GetInstance()->InsertSyncPoint();
354 } else if (skip_frame
) {
355 ack
.mailbox_name
= received_mailbox
;
359 ack
.sync_point
= sync_point
;
360 RenderWidgetHostImpl::AcknowledgeBufferPresent(
361 route_id
, gpu_host_id
, ack
);
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
{
371 explicit EventFilterForPopupExit(RenderWidgetHostViewAura
* rwhva
)
374 aura::Window
* root_window
= rwhva_
->window_
->GetRootWindow();
376 root_window
->AddPreTargetHandler(this);
379 virtual ~EventFilterForPopupExit() {
380 aura::Window
* root_window
= rwhva_
->window_
->GetRootWindow();
382 root_window
->RemovePreTargetHandler(this);
385 // Overridden from ui::EventHandler
386 virtual void OnMouseEvent(ui::MouseEvent
* event
) OVERRIDE
{
387 rwhva_
->ApplyEventFilterForPopupExit(event
);
391 RenderWidgetHostViewAura
* rwhva_
;
393 DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit
);
396 void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
397 ui::MouseEvent
* event
) {
398 if (in_shutdown_
|| is_fullscreen_
)
401 if (event
->type() != ui::ET_MOUSE_PRESSED
|| !event
->target())
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().
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
{
421 explicit WindowObserver(RenderWidgetHostViewAura
* 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();
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)),
454 in_bounds_changed_(false),
455 is_fullscreen_(false),
456 popup_parent_host_view_(NULL
),
457 popup_child_host_view_(NULL
),
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
),
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()));
487 plugin_parent_window_
= NULL
;
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_
;
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
);
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
;
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
);
554 RenderWidgetHost
* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
558 void RenderWidgetHostViewAura::WasShown() {
560 if (!host_
->is_hidden())
563 software_frame_manager_
->SetVisibility(true);
564 delegated_frame_evictor_
->SetVisible(true);
566 aura::Window
* root
= window_
->GetRootWindow();
568 aura::client::CursorClient
* cursor_client
=
569 aura::client::GetCursorClient(root
);
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();
578 released_front_lock_
= compositor
->GetCompositorLock();
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);
594 void RenderWidgetHostViewAura::WasHidden() {
595 if (!host_
|| host_
->is_hidden())
598 software_frame_manager_
->SetVisibility(false);
599 delegated_frame_evictor_
->SetVisible(false);
600 released_front_lock_
= NULL
;
603 constrained_rects_
.clear();
604 aura::WindowEventDispatcher
* dispatcher
= window_
->GetDispatcher();
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);
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();
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())
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.
677 if (host_
->should_auto_resize())
679 if (!host_
->is_accelerated_compositing_active())
682 gfx::Size desired_size
= window_
->bounds().size();
683 if (desired_size
== current_frame_size_
)
686 aura::WindowEventDispatcher
* dispatcher
= window_
->GetDispatcher();
690 ui::Compositor
* compositor
= dispatcher
->compositor();
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(),
703 defer_compositor_lock
,
704 base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs
)));
707 gfx::NativeView
RenderWidgetHostViewAura::GetNativeView() const {
711 gfx::NativeViewId
RenderWidgetHostViewAura::GetNativeViewId() const {
713 aura::WindowEventDispatcher
* dispatcher
= window_
->GetDispatcher();
715 return reinterpret_cast<gfx::NativeViewId
>(
716 dispatcher
->host()->GetAcceleratedWidget());
718 return static_cast<gfx::NativeViewId
>(NULL
);
721 gfx::NativeViewAccessible
RenderWidgetHostViewAura::GetNativeViewAccessible() {
723 aura::WindowEventDispatcher
* dispatcher
= window_
->GetDispatcher();
725 return static_cast<gfx::NativeViewAccessible
>(NULL
);
726 HWND hwnd
= dispatcher
->host()->GetAcceleratedWidget();
728 BrowserAccessibilityManager
* manager
=
729 GetOrCreateBrowserAccessibilityManager();
731 return manager
->GetRoot()->ToBrowserAccessibilityWin();
735 return static_cast<gfx::NativeViewAccessible
>(NULL
);
738 BrowserAccessibilityManager
*
739 RenderWidgetHostViewAura::GetOrCreateBrowserAccessibilityManager() {
740 BrowserAccessibilityManager
* manager
= GetBrowserAccessibilityManager();
745 aura::WindowEventDispatcher
* dispatcher
= window_
->GetDispatcher();
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);
761 manager
= BrowserAccessibilityManager::Create(
762 BrowserAccessibilityManager::GetEmptyDocument(), this);
765 SetBrowserAccessibilityManager(manager
);
769 void RenderWidgetHostViewAura::SetKeyboardFocus() {
772 aura::WindowEventDispatcher
* dispatcher
= window_
->GetDispatcher();
774 ::SetFocus(dispatcher
->host()->GetAcceleratedWidget());
779 void RenderWidgetHostViewAura::MovePluginWindows(
780 const gfx::Vector2d
& scroll_offset
,
781 const std::vector
<WebPluginGeometry
>& plugin_window_moves
) {
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());
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
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_
);
842 void RenderWidgetHostViewAura::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() {
859 void RenderWidgetHostViewAura::Hide() {
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());
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())
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
);
959 aura::WindowEventDispatcher
* dispatcher
= window_
->GetDispatcher();
961 for (size_t i
= 0; i
< copy_rects
.size(); ++i
) {
962 gfx::Rect rect
= gfx::SubtractRects(copy_rects
[i
], scroll_rect
);
966 SchedulePaintIfNotInClip(rect
, clip_rect
);
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
,
983 UpdateCursorIfOverSelf();
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.
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
,
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())
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
)
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();
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());
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
,
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);
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.
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 {
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
,
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())
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_
);
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);
1206 void RenderWidgetHostViewAura::CheckResizeLock() {
1207 if (!resize_lock_
|| resize_lock_
->expected_size() != current_frame_size_
)
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();
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());
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
,
1242 last_swapped_surface_scale_factor_
);
1243 current_frame_size_
= ConvertSizeToDIP(last_swapped_surface_scale_factor_
,
1244 mailbox
.shared_memory_size());
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
>());
1277 ImageTransportFactory
* factory
= ImageTransportFactory::GetInstance();
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
>());
1286 current_surface_
->Consume(mailbox_name
, surface_rect
.size());
1287 released_front_lock_
= NULL
;
1288 UpdateExternalTexture();
1293 void RenderWidgetHostViewAura::SwapBuffersCompleted(
1294 const BufferPresentedCallback
& ack_callback
,
1295 const scoped_refptr
<ui::Texture
>& texture_to_return
) {
1296 ui::Compositor
* compositor
= GetCompositor();
1298 ack_callback
.Run(false, texture_to_return
);
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_
),
1317 base::Bind(callback
, present_time
));
1323 void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
1324 const std::vector
<gfx::Rect
>& rects
) {
1325 if (rects
== constrained_rects_
)
1327 constrained_rects_
= rects
;
1328 UpdateCutoutRects();
1331 void RenderWidgetHostViewAura::UpdateCutoutRects() {
1332 if (!window_
->GetRootWindow())
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
>(¶ms
);
1340 EnumChildWindows(parent
, SetCutoutRectsCallback
, lparam
);
1344 void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
1345 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params
& params_in_pixel
,
1347 BufferPresentedCallback ack_callback
= base::Bind(
1348 &AcknowledgeBufferForGpu
,
1349 params_in_pixel
.route_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
,
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
,
1384 RenderWidgetHostImpl::SendSwapCompositorFrameAck(
1385 host_
->GetRoutingID(), output_surface_id
,
1386 host_
->GetProcess()->GetID(), ack
);
1387 skipped_frames_
= true;
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();
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(),
1443 frame_provider_
->SetFrameData(frame_data
.Pass());
1446 released_front_lock_
= NULL
;
1447 current_frame_size_
= frame_size_in_dip
;
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();
1458 SendDelegatedFrameAck(output_surface_id
);
1460 compositor
->SetLatencyInfo(latency_info
);
1461 AddOnCommitCallbackAndDisableLocks(
1462 base::Bind(&RenderWidgetHostViewAura::SendDelegatedFrameAck
,
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(),
1478 host_
->GetProcess()->GetID(),
1480 DCHECK_GT(pending_delegated_ack_count_
, 0);
1481 pending_delegated_ack_count_
--;
1484 void RenderWidgetHostViewAura::UnusedResourcesAreAvailable() {
1485 if (pending_delegated_ack_count_
)
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(),
1500 host_
->GetProcess()->GetID(),
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
);
1525 if (!software_frame_manager_
->SwapToNewFrame(
1528 frame_device_scale_factor
,
1529 host_
->GetProcess()->GetHandle())) {
1530 ReleaseSoftwareFrame(output_surface_id
, frame_data
->id
);
1531 SendSoftwareFrameAck(output_surface_id
);
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
;
1550 window_
->layer()->SetTextureMailbox(mailbox
,
1552 frame_device_scale_factor
);
1553 window_
->SchedulePaintInRect(
1554 ConvertRectToDIP(frame_device_scale_factor
, damage_rect
));
1556 ui::Compositor
* compositor
= GetCompositor();
1558 compositor
->SetLatencyInfo(latency_info
);
1559 AddOnCommitCallbackAndDisableLocks(
1560 base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck
,
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_
)
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(),
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
);
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
);
1629 if (!frame
->gl_frame_data
|| frame
->gl_frame_data
->mailbox
.IsZero())
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
>());
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
,
1653 frame
->metadata
.latency_info
,
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()
1668 return reinterpret_cast<gfx::NativeViewId
>(plugin_parent_window_
);
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
,
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(),
1715 previous_damage_
= damage
;
1717 ui::Compositor
* compositor
= GetCompositor();
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
,
1746 gfx::Rect
damage_rect(params_in_pixel
.x
,
1748 params_in_pixel
.width
,
1749 params_in_pixel
.height
);
1750 BufferPresentedCallback ack_callback
=
1751 base::Bind(&AcknowledgeBufferForGpu
,
1752 params_in_pixel
.route_id
,
1754 params_in_pixel
.mailbox_name
);
1755 BuffersSwapped(params_in_pixel
.surface_size
,
1757 params_in_pixel
.surface_scale_factor
,
1758 params_in_pixel
.mailbox_name
,
1759 params_in_pixel
.latency_info
,
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();
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
,
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.
1792 void RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor(
1793 scoped_refptr
<ui::Texture
>) {
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());
1806 if (result
->HasTexture()) {
1807 PrepareTextureCopyOutputResult(dst_size_in_pixel
, callback
, result
.Pass());
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
,
1821 bitmap_pixels_lock
.reset();
1822 release_callback
->Run(0, false);
1823 callback
.Run(result
, *bitmap
);
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())
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())
1845 ImageTransportFactory
* factory
= ImageTransportFactory::GetInstance();
1846 GLHelper
* gl_helper
= factory
->GetGLHelper();
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())
1861 ignore_result(scoped_callback_runner
.Release());
1863 gl_helper
->CropScaleReadbackAndCleanMailbox(
1864 texture_mailbox
.name(),
1865 texture_mailbox
.sync_point(),
1867 gfx::Rect(result
->size()),
1870 base::Bind(&CopyFromCompositingSurfaceFinished
,
1872 base::Passed(&release_callback
),
1873 base::Passed(&bitmap
),
1874 base::Passed(&bitmap_pixels_lock
)));
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())
1889 scoped_ptr
<SkBitmap
> source
= result
->TakeBitmap();
1894 ignore_result(scoped_callback_runner
.Release());
1896 SkBitmap bitmap
= skia::ImageOperations::Resize(
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
,
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);
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
;
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));
1939 if (result
->IsEmpty())
1941 if (result
->size().IsEmpty())
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
1950 gfx::Rect region_in_frame
=
1951 media::ComputeLetterboxRegion(gfx::Rect(video_frame
->coded_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())
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());
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(),
1987 ignore_result(scoped_callback_runner
.Release());
1992 ImageTransportFactory
* factory
= ImageTransportFactory::GetInstance();
1993 GLHelper
* gl_helper
= factory
->GetGLHelper();
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())
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
,
2032 video_frame
->coded_size(),
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
,
2045 base::Passed(&release_callback
));
2046 yuv_readback_pipeline
->ReadbackYUV(
2047 texture_mailbox
.name(),
2048 texture_mailbox
.sync_point(),
2053 void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo
* results
) {
2054 GetScreenInfoForWindow(results
, window_
->GetRootWindow() ? window_
: NULL
);
2057 gfx::Rect
RenderWidgetHostViewAura::GetBoundsInRootWindow() {
2059 // aura::Window::GetBoundsInScreen doesn't take non-client area into
2061 RECT window_rect
= {0};
2063 aura::Window
* top_level
= window_
->GetToplevelWindow();
2064 aura::WindowEventDispatcher
* dispatcher
= top_level
->GetDispatcher();
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
);
2082 return window_
->GetToplevelWindow()->GetBoundsInScreen();
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
))
2099 aura::WindowEventDispatcher
* dispatcher
= window_
->GetDispatcher();
2100 // |dispatcher| is NULL during tests.
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();
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();
2154 mouse_locked_
= true;
2155 #if !defined(OS_WIN)
2156 window_
->SetCapture();
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();
2176 void RenderWidgetHostViewAura::UnlockMouse() {
2177 aura::Window
* root_window
= window_
->GetRootWindow();
2178 if (!mouse_locked_
|| !root_window
)
2181 mouse_locked_
= false;
2183 #if !defined(OS_WIN)
2184 window_
->ReleaseCapture();
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
) {
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(),
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
);
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
);
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
,
2265 host_
->ForwardKeyboardEvent(webkit_event
);
2269 gfx::NativeWindow
RenderWidgetHostViewAura::GetAttachedWindow() const {
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();
2293 aura::client::ScreenPositionClient
* screen_position_client
=
2294 aura::client::GetScreenPositionClient(root_window
);
2295 if (!screen_position_client
)
2297 screen_position_client
->ConvertPointToScreen(window_
, &origin
);
2298 screen_position_client
->ConvertPointToScreen(window_
, &end
);
2299 return gfx::Rect(origin
.x(),
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();
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(),
2318 end
.x() - origin
.x(),
2319 end
.y() - origin
.y());
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(
2333 gfx::Rect
* rect
) const {
2335 if (index
>= composition_character_bounds_
.size())
2337 *rect
= ConvertRectToScreen(composition_character_bounds_
[index
]);
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());
2351 bool RenderWidgetHostViewAura::GetCompositionTextRange(
2352 gfx::Range
* range
) const {
2353 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
2358 bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range
* range
) const {
2359 range
->set_start(selection_range_
.start());
2360 range
->set_end(selection_range_
.end());
2364 bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range
& range
) {
2365 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
2370 bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range
& range
) {
2371 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
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
)) {
2386 if (selection_text_range
.EqualsIgnoringDirection(range
)) {
2387 // Avoid calling substr whose performance is low.
2388 *text
= selection_text_
;
2390 *text
= selection_text_
.substr(
2391 range
.GetMin() - selection_text_offset_
,
2397 void RenderWidgetHostViewAura::OnInputMethodChanged() {
2401 if (GetInputMethod())
2402 host_
->SetInputMethodActive(GetInputMethod()->IsActive());
2404 // TODO(suzhe): implement the newly added “locale” property of HTML DOM
2408 bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
2409 base::i18n::TextDirection direction
) {
2412 host_
->UpdateTextDirection(
2413 direction
== base::i18n::RIGHT_TO_LEFT
?
2414 blink::WebTextDirectionRightToLeft
:
2415 blink::WebTextDirectionLeftToRight
);
2416 host_
->NotifyTextDirection();
2420 void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
2421 size_t before
, size_t after
) {
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())
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 {
2477 gfx::Size
RenderWidgetHostViewAura::GetMaximumSize() const {
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.
2488 SetSize(new_bounds
.size());
2491 gfx::NativeCursor
RenderWidgetHostViewAura::GetCursor(const gfx::Point
& point
) {
2493 return ui::kCursorNone
;
2494 return current_cursor_
.GetNativeCursor();
2497 int RenderWidgetHostViewAura::GetNonClientComponent(
2498 const gfx::Point
& point
) const {
2502 bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
2503 aura::Window
* child
,
2504 const gfx::Point
& location
) {
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();
2531 compositor
->SetLatencyInfo(software_latency_info_
);
2532 software_latency_info_
.Clear();
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
2538 if (window_
->layer()->fills_bounds_opaquely())
2539 canvas
->DrawColor(SK_ColorWHITE
);
2543 void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
2544 float device_scale_factor
) {
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() {
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();
2569 parent
= window_
->GetDispatcher()->host()->GetAcceleratedWidget();
2571 LPARAM lparam
= reinterpret_cast<LPARAM
>(this);
2572 EnumChildWindows(parent
, WindowDestroyingCallback
, lparam
);
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();
2580 input_method
->DetachTextInputClient(this);
2583 void RenderWidgetHostViewAura::OnWindowDestroyed() {
2584 host_
->ViewDestroyed();
2588 void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible
) {
2591 bool RenderWidgetHostViewAura::HasHitTestMask() const {
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());
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());
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
,
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
))
2660 if (popup_child_host_view_
&& popup_child_host_view_
->NeedsInputGrab()) {
2661 popup_child_host_view_
->OnKeyEvent(event
);
2662 if (event
->handled())
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
);
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
);
2679 if (!tracker
.Contains(window
)) {
2680 event
->SetHandled();
2685 if (!in_shutdown_
) {
2686 in_shutdown_
= true;
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(
2699 event
->is_char() ? event
->GetCharacter() : event
->key_code(),
2701 ui::EventTimeForNow().InSecondsF());
2702 host_
->ForwardKeyboardEvent(webkit_event
);
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
))
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
);
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
);
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;
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
)
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
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();
2787 if (event
->type() == ui::ET_MOUSEWHEEL
) {
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
2792 aura::WindowEventDispatcher
* dispatcher
= window_
->GetDispatcher();
2794 HWND parent
= dispatcher
->host()->GetAcceleratedWidget();
2795 HWND toplevel_hwnd
= ::GetAncestor(parent
, GA_ROOT
);
2796 EnumThreadWindows(GetCurrentThreadId(),
2798 reinterpret_cast<LPARAM
>(toplevel_hwnd
));
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
)
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();
2823 case ui::ET_MOUSE_RELEASED
:
2824 window_
->ReleaseCapture();
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
))
2848 if (event
->type() == ui::ET_SCROLL
) {
2849 if (event
->finger_count() != 2)
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
))
2875 // Update the touch event first.
2876 blink::WebTouchPoint
* point
= UpdateWebTouchEventFromUIEvent(*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();
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();
2905 if (touch_editing_client_
&& touch_editing_client_
->HandleInputEvent(event
))
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();
2956 const ui::Event
* event
= dispatcher
->current_event();
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())
2997 host_
->SetActive(true);
2999 ui::InputMethod
* input_method
= GetInputMethod();
3001 // Ask the system-wide IME to send all TextInputClient messages to |this|
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
3009 host_
->SuppressNextCharEvents();
3011 host_
->SetInputMethodActive(false);
3013 } else if (window_
== lost_focus
) {
3014 host_
->SetActive(false);
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
) {
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
) {
3037 ::GetCursorPos(&point
);
3038 if (screen
->GetDisplayNearestWindow(window_
).id() !=
3039 screen
->GetDisplayNearestPoint(gfx::Point(point
)).id())
3043 in_shutdown_
= true;
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();
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
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
) {
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
) {
3147 host_
->AccessibilitySetFocus(acc_obj_id
);
3150 void RenderWidgetHostViewAura::AccessibilityDoDefaultAction(int acc_obj_id
) {
3154 host_
->AccessibilityDoDefaultAction(acc_obj_id
);
3157 void RenderWidgetHostViewAura::AccessibilityScrollToMakeVisible(
3158 int acc_obj_id
, gfx::Rect subfocus
) {
3162 host_
->AccessibilityScrollToMakeVisible(acc_obj_id
, subfocus
);
3165 void RenderWidgetHostViewAura::AccessibilityScrollToPoint(
3166 int acc_obj_id
, gfx::Point point
) {
3170 host_
->AccessibilityScrollToPoint(acc_obj_id
, point
);
3173 void RenderWidgetHostViewAura::AccessibilitySetTextSelection(
3174 int acc_obj_id
, int start_offset
, int end_offset
) {
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);
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
);
3253 if (::IsWindow(plugin_parent_window_
))
3254 ::DestroyWindow(plugin_parent_window_
);
3258 void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
3259 const gfx::Point screen_point
=
3260 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
3261 aura::Window
* root_window
= window_
->GetRootWindow();
3265 gfx::Rect screen_rect
= GetViewBounds();
3266 gfx::Point local_point
= screen_point
;
3267 local_point
.Offset(-screen_rect
.x(), -screen_rect
.y());
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
))
3278 if (root_window
->GetEventHandlerForPoint(local_point
) != window_
)
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();
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_
)
3308 host_
->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
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
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();
3343 unlocked_mouse_position_
.SetPoint(event
->windowX
, event
->windowY
);
3344 unlocked_global_mouse_position_
.SetPoint(event
->globalX
, event
->globalY
);
3348 void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
3350 if (host_
->is_hidden() ||
3351 (cursor_visibility_state_in_renderer_
== VISIBLE
&& is_visible
) ||
3352 (cursor_visibility_state_in_renderer_
== NOT_VISIBLE
&& !is_visible
))
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
);
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
) {
3389 on_compositing_did_commit_callbacks_
.clear();
3392 void RenderWidgetHostViewAura::AddOnCommitCallbackAndDisableLocks(
3393 const base::Closure
& callback
) {
3394 ui::Compositor
* compositor
= GetCompositor();
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());
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
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:
3463 RenderWidgetHostView
* RenderWidgetHostView::CreateViewForWidget(
3464 RenderWidgetHost
* widget
) {
3465 return new RenderWidgetHostViewAura(widget
);
3469 void RenderWidgetHostViewPort::GetDefaultScreenInfo(WebScreenInfo
* results
) {
3470 GetScreenInfoForWindow(results
, NULL
);
3473 } // namespace content