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"
9 #include "base/auto_reset.h"
10 #include "base/basictypes.h"
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/command_line.h"
14 #include "base/logging.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/trace_event/trace_event.h"
18 #include "cc/layers/layer.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/bad_message.h"
26 #include "content/browser/frame_host/frame_tree.h"
27 #include "content/browser/frame_host/frame_tree_node.h"
28 #include "content/browser/frame_host/render_frame_host_impl.h"
29 #include "content/browser/gpu/compositor_util.h"
30 #include "content/browser/renderer_host/compositor_resize_lock_aura.h"
31 #include "content/browser/renderer_host/dip_util.h"
32 #include "content/browser/renderer_host/input/synthetic_gesture_target_aura.h"
33 #include "content/browser/renderer_host/input/touch_selection_controller_client_aura.h"
34 #include "content/browser/renderer_host/input/ui_touch_selection_helper.h"
35 #include "content/browser/renderer_host/input/web_input_event_util.h"
36 #include "content/browser/renderer_host/overscroll_controller.h"
37 #include "content/browser/renderer_host/render_view_host_delegate.h"
38 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
39 #include "content/browser/renderer_host/render_view_host_impl.h"
40 #include "content/browser/renderer_host/render_widget_host_delegate.h"
41 #include "content/browser/renderer_host/render_widget_host_impl.h"
42 #include "content/browser/renderer_host/render_widget_host_input_event_router.h"
43 #include "content/browser/renderer_host/ui_events_helper.h"
44 #include "content/browser/renderer_host/web_input_event_aura.h"
45 #include "content/common/gpu/client/gl_helper.h"
46 #include "content/common/gpu/gpu_messages.h"
47 #include "content/common/view_messages.h"
48 #include "content/public/browser/content_browser_client.h"
49 #include "content/public/browser/overscroll_configuration.h"
50 #include "content/public/browser/render_view_host.h"
51 #include "content/public/browser/render_widget_host_view_frame_subscriber.h"
52 #include "content/public/browser/user_metrics.h"
53 #include "content/public/common/content_switches.h"
54 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
55 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
56 #include "third_party/WebKit/public/web/WebInputEvent.h"
57 #include "ui/aura/client/aura_constants.h"
58 #include "ui/aura/client/cursor_client.h"
59 #include "ui/aura/client/cursor_client_observer.h"
60 #include "ui/aura/client/focus_client.h"
61 #include "ui/aura/client/screen_position_client.h"
62 #include "ui/aura/client/window_tree_client.h"
63 #include "ui/aura/env.h"
64 #include "ui/aura/window.h"
65 #include "ui/aura/window_event_dispatcher.h"
66 #include "ui/aura/window_observer.h"
67 #include "ui/aura/window_tracker.h"
68 #include "ui/aura/window_tree_host.h"
69 #include "ui/base/clipboard/scoped_clipboard_writer.h"
70 #include "ui/base/hit_test.h"
71 #include "ui/base/ime/input_method.h"
72 #include "ui/base/ui_base_types.h"
73 #include "ui/compositor/compositor_vsync_manager.h"
74 #include "ui/compositor/dip_util.h"
75 #include "ui/events/blink/blink_event_util.h"
76 #include "ui/events/event.h"
77 #include "ui/events/event_utils.h"
78 #include "ui/events/gesture_detection/gesture_configuration.h"
79 #include "ui/events/gestures/gesture_recognizer.h"
80 #include "ui/gfx/canvas.h"
81 #include "ui/gfx/color_profile.h"
82 #include "ui/gfx/display.h"
83 #include "ui/gfx/geometry/rect_conversions.h"
84 #include "ui/gfx/geometry/size_conversions.h"
85 #include "ui/gfx/screen.h"
86 #include "ui/gfx/skia_util.h"
87 #include "ui/touch_selection/touch_selection_controller.h"
88 #include "ui/wm/public/activation_client.h"
89 #include "ui/wm/public/scoped_tooltip_disabler.h"
90 #include "ui/wm/public/tooltip_client.h"
91 #include "ui/wm/public/transient_window_client.h"
92 #include "ui/wm/public/window_types.h"
95 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
96 #include "content/browser/accessibility/browser_accessibility_win.h"
97 #include "content/browser/renderer_host/legacy_render_widget_host_win.h"
98 #include "content/common/plugin_constants_win.h"
99 #include "ui/base/win/hidden_window.h"
100 #include "ui/gfx/gdi_util.h"
101 #include "ui/gfx/win/dpi.h"
104 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
105 #include "content/common/input_messages.h"
106 #include "ui/events/linux/text_edit_command_auralinux.h"
107 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
110 using gfx::RectToSkIRect
;
111 using gfx::SkIRectToRect
;
113 using blink::WebScreenInfo
;
114 using blink::WebInputEvent
;
115 using blink::WebGestureEvent
;
116 using blink::WebTouchEvent
;
122 // In mouse lock mode, we need to prevent the (invisible) cursor from hitting
123 // the border of the view, in order to get valid movement information. However,
124 // forcing the cursor back to the center of the view after each mouse move
125 // doesn't work well. It reduces the frequency of useful mouse move messages
126 // significantly. Therefore, we move the cursor to the center of the view only
127 // if it approaches the border. |kMouseLockBorderPercentage| specifies the width
128 // of the border area, in percentage of the corresponding dimension.
129 const int kMouseLockBorderPercentage
= 15;
131 // When accelerated compositing is enabled and a widget resize is pending,
132 // we delay further resizes of the UI. The following constant is the maximum
133 // length of time that we should delay further UI resizes while waiting for a
134 // resized frame from a renderer.
135 const int kResizeLockTimeoutMs
= 67;
138 // Used to associate a plugin HWND with its RenderWidgetHostViewAura instance.
139 const wchar_t kWidgetOwnerProperty
[] = L
"RenderWidgetHostViewAuraOwner";
141 BOOL CALLBACK
WindowDestroyingCallback(HWND window
, LPARAM param
) {
142 RenderWidgetHostViewAura
* widget
=
143 reinterpret_cast<RenderWidgetHostViewAura
*>(param
);
144 if (GetProp(window
, kWidgetOwnerProperty
) == widget
) {
145 // Properties set on HWNDs must be removed to avoid leaks.
146 RemoveProp(window
, kWidgetOwnerProperty
);
147 RenderWidgetHostViewBase::DetachPluginWindowsCallback(window
);
152 BOOL CALLBACK
HideWindowsCallback(HWND window
, LPARAM param
) {
153 RenderWidgetHostViewAura
* widget
=
154 reinterpret_cast<RenderWidgetHostViewAura
*>(param
);
155 if (GetProp(window
, kWidgetOwnerProperty
) == widget
)
156 SetParent(window
, ui::GetHiddenWindow());
160 BOOL CALLBACK
ShowWindowsCallback(HWND window
, LPARAM param
) {
161 RenderWidgetHostViewAura
* widget
=
162 reinterpret_cast<RenderWidgetHostViewAura
*>(param
);
164 if (GetProp(window
, kWidgetOwnerProperty
) == widget
&&
165 widget
->GetNativeView()->GetHost()) {
166 HWND parent
= widget
->GetNativeView()->GetHost()->GetAcceleratedWidget();
167 SetParent(window
, parent
);
172 struct CutoutRectsParams
{
173 RenderWidgetHostViewAura
* widget
;
174 std::vector
<gfx::Rect
> cutout_rects
;
175 std::map
<HWND
, WebPluginGeometry
>* geometry
;
178 // Used to update the region for the windowed plugin to draw in. We start with
179 // the clip rect from the renderer, then remove the cutout rects from the
180 // renderer, and then remove the transient windows from the root window and the
181 // constrained windows from the parent window.
182 BOOL CALLBACK
SetCutoutRectsCallback(HWND window
, LPARAM param
) {
183 CutoutRectsParams
* params
= reinterpret_cast<CutoutRectsParams
*>(param
);
185 if (GetProp(window
, kWidgetOwnerProperty
) == params
->widget
) {
186 // First calculate the offset of this plugin from the root window, since
187 // the cutouts are relative to the root window.
189 params
->widget
->GetNativeView()->GetHost()->GetAcceleratedWidget();
191 offset
.x
= offset
.y
= 0;
192 MapWindowPoints(window
, parent
, &offset
, 1);
194 // Now get the cached clip rect and cutouts for this plugin window that came
195 // from the renderer.
196 std::map
<HWND
, WebPluginGeometry
>::iterator i
= params
->geometry
->begin();
197 while (i
!= params
->geometry
->end() &&
198 i
->second
.window
!= window
&&
199 GetParent(i
->second
.window
) != window
) {
203 if (i
== params
->geometry
->end()) {
208 HRGN hrgn
= CreateRectRgn(i
->second
.clip_rect
.x(),
209 i
->second
.clip_rect
.y(),
210 i
->second
.clip_rect
.right(),
211 i
->second
.clip_rect
.bottom());
212 // We start with the cutout rects that came from the renderer, then add the
213 // ones that came from transient and constrained windows.
214 std::vector
<gfx::Rect
> cutout_rects
= i
->second
.cutout_rects
;
215 for (size_t i
= 0; i
< params
->cutout_rects
.size(); ++i
) {
216 gfx::Rect offset_cutout
= params
->cutout_rects
[i
];
217 offset_cutout
.Offset(-offset
.x
, -offset
.y
);
218 cutout_rects
.push_back(offset_cutout
);
220 gfx::SubtractRectanglesFromRegion(hrgn
, cutout_rects
);
221 // If we don't have any cutout rects then no point in messing with the
223 if (cutout_rects
.size())
224 SetWindowRgn(window
, hrgn
, TRUE
);
229 // A callback function for EnumThreadWindows to enumerate and dismiss
230 // any owned popup windows.
231 BOOL CALLBACK
DismissOwnedPopups(HWND window
, LPARAM arg
) {
232 const HWND toplevel_hwnd
= reinterpret_cast<HWND
>(arg
);
234 if (::IsWindowVisible(window
)) {
235 const HWND owner
= ::GetWindow(window
, GW_OWNER
);
236 if (toplevel_hwnd
== owner
) {
237 ::PostMessage(window
, WM_CANCELMODE
, 0, 0);
245 // We don't mark these as handled so that they're sent back to the
246 // DefWindowProc so it can generate WM_APPCOMMAND as necessary.
247 bool IsXButtonUpEvent(const ui::MouseEvent
* event
) {
249 switch (event
->native_event().message
) {
258 void GetScreenInfoForWindow(WebScreenInfo
* results
, aura::Window
* window
) {
259 const gfx::Display display
= window
?
260 gfx::Screen::GetScreenFor(window
)->GetDisplayNearestWindow(window
) :
261 gfx::Screen::GetScreenFor(window
)->GetPrimaryDisplay();
262 results
->rect
= display
.bounds();
263 results
->availableRect
= display
.work_area();
264 // TODO(derat|oshima): Don't hardcode this. Get this from display object.
266 results
->depthPerComponent
= 8;
267 results
->deviceScaleFactor
= display
.device_scale_factor();
269 // The Display rotation and the WebScreenInfo orientation are not the same
270 // angle. The former is the physical display rotation while the later is the
271 // rotation required by the content to be shown properly on the screen, in
272 // other words, relative to the physical display.
273 results
->orientationAngle
= display
.RotationAsDegree();
274 if (results
->orientationAngle
== 90)
275 results
->orientationAngle
= 270;
276 else if (results
->orientationAngle
== 270)
277 results
->orientationAngle
= 90;
279 results
->orientationType
=
280 RenderWidgetHostViewBase::GetOrientationTypeForDesktop(display
);
283 bool IsFractionalScaleFactor(float scale_factor
) {
284 return (scale_factor
- static_cast<int>(scale_factor
)) > 0;
287 // Reset unchanged touch point to StateStationary for touchmove and
289 void MarkUnchangedTouchPointsAsStationary(
290 blink::WebTouchEvent
* event
,
291 int changed_touch_id
) {
292 if (event
->type
== blink::WebInputEvent::TouchMove
||
293 event
->type
== blink::WebInputEvent::TouchCancel
) {
294 for (size_t i
= 0; i
< event
->touchesLength
; ++i
) {
295 if (event
->touches
[i
].id
!= changed_touch_id
)
296 event
->touches
[i
].state
= blink::WebTouchPoint::StateStationary
;
303 // We need to watch for mouse events outside a Web Popup or its parent
304 // and dismiss the popup for certain events.
305 class RenderWidgetHostViewAura::EventFilterForPopupExit
306 : public ui::EventHandler
{
308 explicit EventFilterForPopupExit(RenderWidgetHostViewAura
* rwhva
)
311 aura::Env::GetInstance()->AddPreTargetHandler(this);
314 ~EventFilterForPopupExit() override
{
315 aura::Env::GetInstance()->RemovePreTargetHandler(this);
318 // Overridden from ui::EventHandler
319 void OnMouseEvent(ui::MouseEvent
* event
) override
{
320 rwhva_
->ApplyEventFilterForPopupExit(event
);
323 void OnTouchEvent(ui::TouchEvent
* event
) override
{
324 rwhva_
->ApplyEventFilterForPopupExit(event
);
328 RenderWidgetHostViewAura
* rwhva_
;
330 DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit
);
333 void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
334 ui::LocatedEvent
* event
) {
335 if (in_shutdown_
|| is_fullscreen_
|| !event
->target())
338 if (event
->type() != ui::ET_MOUSE_PRESSED
&&
339 event
->type() != ui::ET_TOUCH_PRESSED
) {
343 aura::Window
* target
= static_cast<aura::Window
*>(event
->target());
344 if (target
!= window_
&&
345 (!popup_parent_host_view_
||
346 target
!= popup_parent_host_view_
->window_
)) {
347 // If we enter this code path it means that we did not receive any focus
348 // lost notifications for the popup window. Ensure that blink is aware
349 // of the fact that focus was lost for the host window by sending a Blur
350 // notification. We also set a flag in the view indicating that we need
351 // to force a Focus notification on the next mouse down.
352 if (popup_parent_host_view_
&& popup_parent_host_view_
->host_
) {
353 popup_parent_host_view_
->set_focus_on_mouse_down_
= true;
354 popup_parent_host_view_
->host_
->Blur();
356 // Note: popup_parent_host_view_ may be NULL when there are multiple
357 // popup children per view. See: RenderWidgetHostViewAura::InitAsPopup().
362 // We have to implement the WindowObserver interface on a separate object
363 // because clang doesn't like implementing multiple interfaces that have
364 // methods with the same name. This object is owned by the
365 // RenderWidgetHostViewAura.
366 class RenderWidgetHostViewAura::WindowObserver
: public aura::WindowObserver
{
368 explicit WindowObserver(RenderWidgetHostViewAura
* view
)
370 view_
->window_
->AddObserver(this);
373 ~WindowObserver() override
{ view_
->window_
->RemoveObserver(this); }
375 // Overridden from aura::WindowObserver:
376 void OnWindowAddedToRootWindow(aura::Window
* window
) override
{
377 if (window
== view_
->window_
)
378 view_
->AddedToRootWindow();
381 void OnWindowRemovingFromRootWindow(aura::Window
* window
,
382 aura::Window
* new_root
) override
{
383 if (window
== view_
->window_
)
384 view_
->RemovingFromRootWindow();
387 void OnWindowHierarchyChanged(const HierarchyChangeParams
& params
) override
{
388 view_
->ParentHierarchyChanged();
392 RenderWidgetHostViewAura
* view_
;
394 DISALLOW_COPY_AND_ASSIGN(WindowObserver
);
397 // This class provides functionality to observe the ancestors of the RWHVA for
398 // bounds changes. This is done to snap the RWHVA window to a pixel boundary,
399 // which could change when the bounds relative to the root changes.
400 // An example where this happens is below:-
401 // The fast resize code path for bookmarks where in the parent of RWHVA which
402 // is WCV has its bounds changed before the bookmark is hidden. This results in
403 // the traditional bounds change notification for the WCV reporting the old
404 // bounds as the bookmark is still around. Observing all the ancestors of the
405 // RWHVA window enables us to know when the bounds of the window relative to
406 // root changes and allows us to snap accordingly.
407 class RenderWidgetHostViewAura::WindowAncestorObserver
408 : public aura::WindowObserver
{
410 explicit WindowAncestorObserver(RenderWidgetHostViewAura
* view
)
412 aura::Window
* parent
= view_
->window_
->parent();
414 parent
->AddObserver(this);
415 ancestors_
.insert(parent
);
416 parent
= parent
->parent();
420 ~WindowAncestorObserver() override
{
421 RemoveAncestorObservers();
424 void OnWindowBoundsChanged(aura::Window
* window
,
425 const gfx::Rect
& old_bounds
,
426 const gfx::Rect
& new_bounds
) override
{
427 DCHECK(ancestors_
.find(window
) != ancestors_
.end());
428 if (new_bounds
.origin() != old_bounds
.origin())
429 view_
->HandleParentBoundsChanged();
433 void RemoveAncestorObservers() {
434 for (auto ancestor
: ancestors_
)
435 ancestor
->RemoveObserver(this);
439 RenderWidgetHostViewAura
* view_
;
440 std::set
<aura::Window
*> ancestors_
;
442 DISALLOW_COPY_AND_ASSIGN(WindowAncestorObserver
);
445 ////////////////////////////////////////////////////////////////////////////////
446 // RenderWidgetHostViewAura, public:
448 RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost
* host
,
449 bool is_guest_view_hack
)
450 : host_(RenderWidgetHostImpl::From(host
)),
451 window_(new aura::Window(this)),
452 delegated_frame_host_(new DelegatedFrameHost(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 text_input_flags_(0),
462 can_compose_inline_(true),
463 has_composition_text_(false),
464 accept_return_character_(false),
465 last_swapped_software_frame_scale_factor_(1.f
),
467 synthetic_move_sent_(false),
468 cursor_visibility_state_in_renderer_(UNKNOWN
),
470 legacy_render_widget_host_HWND_(NULL
),
471 legacy_window_destroyed_(false),
472 showing_context_menu_(false),
474 has_snapped_to_boundary_(false),
475 is_guest_view_hack_(is_guest_view_hack
),
476 begin_frame_observer_proxy_(this),
477 set_focus_on_mouse_down_(false),
478 weak_ptr_factory_(this) {
479 if (!is_guest_view_hack_
)
480 host_
->SetView(this);
482 window_observer_
.reset(new WindowObserver(this));
484 aura::client::SetTooltipText(window_
, &tooltip_
);
485 aura::client::SetActivationDelegate(window_
, this);
486 aura::client::SetFocusChangeObserver(window_
, this);
487 window_
->set_layer_owner_delegate(delegated_frame_host_
.get());
488 gfx::Screen::GetScreenFor(window_
)->AddObserver(this);
490 // Let the page-level input event router know about our surface ID
491 // namespace for surface-based hit testing.
492 if (UseSurfacesEnabled() && host_
->delegate() &&
493 host_
->delegate()->GetInputEventRouter()) {
494 host_
->delegate()->GetInputEventRouter()->AddSurfaceIdNamespaceOwner(
495 GetSurfaceIdNamespace(), this);
498 bool overscroll_enabled
= base::CommandLine::ForCurrentProcess()->
499 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation
) != "0";
500 SetOverscrollControllerEnabled(overscroll_enabled
);
502 selection_controller_client_
.reset(
503 new TouchSelectionControllerClientAura(this));
504 CreateSelectionController();
507 ////////////////////////////////////////////////////////////////////////////////
508 // RenderWidgetHostViewAura, RenderWidgetHostView implementation:
510 bool RenderWidgetHostViewAura::OnMessageReceived(
511 const IPC::Message
& message
) {
513 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAura
, message
)
514 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrames
,
515 OnSetNeedsBeginFrames
)
516 IPC_MESSAGE_UNHANDLED(handled
= false)
517 IPC_END_MESSAGE_MAP()
521 void RenderWidgetHostViewAura::InitAsChild(
522 gfx::NativeView parent_view
) {
523 window_
->SetType(ui::wm::WINDOW_TYPE_CONTROL
);
524 window_
->Init(ui::LAYER_SOLID_COLOR
);
525 window_
->SetName("RenderWidgetHostViewAura");
526 window_
->layer()->SetColor(background_color_
);
529 void RenderWidgetHostViewAura::InitAsPopup(
530 RenderWidgetHostView
* parent_host_view
,
531 const gfx::Rect
& bounds_in_screen
) {
532 popup_parent_host_view_
=
533 static_cast<RenderWidgetHostViewAura
*>(parent_host_view
);
535 // TransientWindowClient may be NULL during tests.
536 aura::client::TransientWindowClient
* transient_window_client
=
537 aura::client::GetTransientWindowClient();
538 RenderWidgetHostViewAura
* old_child
=
539 popup_parent_host_view_
->popup_child_host_view_
;
541 // TODO(jhorwich): Allow multiple popup_child_host_view_ per view, or
542 // similar mechanism to ensure a second popup doesn't cause the first one
543 // to never get a chance to filter events. See crbug.com/160589.
544 DCHECK(old_child
->popup_parent_host_view_
== popup_parent_host_view_
);
545 if (transient_window_client
) {
546 transient_window_client
->RemoveTransientChild(
547 popup_parent_host_view_
->window_
, old_child
->window_
);
549 old_child
->popup_parent_host_view_
= NULL
;
551 popup_parent_host_view_
->popup_child_host_view_
= this;
552 window_
->SetType(ui::wm::WINDOW_TYPE_MENU
);
553 window_
->Init(ui::LAYER_SOLID_COLOR
);
554 window_
->SetName("RenderWidgetHostViewAura");
555 window_
->layer()->SetColor(background_color_
);
557 // Setting the transient child allows for the popup to get mouse events when
558 // in a system modal dialog. Do this before calling ParentWindowWithContext
559 // below so that the transient parent is visible to WindowTreeClient.
560 // This fixes crbug.com/328593.
561 if (transient_window_client
) {
562 transient_window_client
->AddTransientChild(
563 popup_parent_host_view_
->window_
, window_
);
566 aura::Window
* root
= popup_parent_host_view_
->window_
->GetRootWindow();
567 aura::client::ParentWindowWithContext(window_
, root
, bounds_in_screen
);
569 SetBounds(bounds_in_screen
);
571 if (NeedsMouseCapture())
572 window_
->SetCapture();
574 event_filter_for_popup_exit_
.reset(new EventFilterForPopupExit(this));
577 void RenderWidgetHostViewAura::InitAsFullscreen(
578 RenderWidgetHostView
* reference_host_view
) {
579 is_fullscreen_
= true;
580 window_
->SetType(ui::wm::WINDOW_TYPE_NORMAL
);
581 window_
->Init(ui::LAYER_SOLID_COLOR
);
582 window_
->SetName("RenderWidgetHostViewAura");
583 window_
->SetProperty(aura::client::kShowStateKey
, ui::SHOW_STATE_FULLSCREEN
);
584 window_
->layer()->SetColor(background_color_
);
586 aura::Window
* parent
= NULL
;
588 if (reference_host_view
) {
589 aura::Window
* reference_window
=
590 static_cast<RenderWidgetHostViewAura
*>(reference_host_view
)->window_
;
591 if (reference_window
) {
592 host_tracker_
.reset(new aura::WindowTracker
);
593 host_tracker_
->Add(reference_window
);
595 gfx::Display display
= gfx::Screen::GetScreenFor(window_
)->
596 GetDisplayNearestWindow(reference_window
);
597 parent
= reference_window
->GetRootWindow();
598 bounds
= display
.bounds();
600 aura::client::ParentWindowWithContext(window_
, parent
, bounds
);
605 RenderWidgetHost
* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
609 void RenderWidgetHostViewAura::Show() {
612 if (!host_
->is_hidden())
615 bool has_saved_frame
= delegated_frame_host_
->HasSavedFrame();
616 ui::LatencyInfo renderer_latency_info
, browser_latency_info
;
617 if (has_saved_frame
) {
618 browser_latency_info
.AddLatencyNumber(
619 ui::TAB_SHOW_COMPONENT
, host_
->GetLatencyComponentId(), 0);
621 renderer_latency_info
.AddLatencyNumber(
622 ui::TAB_SHOW_COMPONENT
, host_
->GetLatencyComponentId(), 0);
624 host_
->WasShown(renderer_latency_info
);
626 aura::Window
* root
= window_
->GetRootWindow();
628 aura::client::CursorClient
* cursor_client
=
629 aura::client::GetCursorClient(root
);
631 NotifyRendererOfCursorVisibilityState(cursor_client
->IsCursorVisible());
634 delegated_frame_host_
->WasShown(browser_latency_info
);
637 if (legacy_render_widget_host_HWND_
) {
638 // Reparent the legacy Chrome_RenderWidgetHostHWND window to the parent
639 // window before reparenting any plugins. This ensures that the plugin
640 // windows stay on top of the child Zorder in the parent and receive
641 // mouse events, etc.
642 legacy_render_widget_host_HWND_
->UpdateParent(
643 GetNativeView()->GetHost()->GetAcceleratedWidget());
644 legacy_render_widget_host_HWND_
->SetBounds(
645 window_
->GetBoundsInRootWindow());
647 LPARAM lparam
= reinterpret_cast<LPARAM
>(this);
648 EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback
, lparam
);
650 if (legacy_render_widget_host_HWND_
)
651 legacy_render_widget_host_HWND_
->Show();
655 void RenderWidgetHostViewAura::Hide() {
658 if (host_
&& !host_
->is_hidden()) {
660 delegated_frame_host_
->WasHidden();
663 constrained_rects_
.clear();
664 aura::WindowTreeHost
* host
= window_
->GetHost();
666 HWND parent
= host
->GetAcceleratedWidget();
667 LPARAM lparam
= reinterpret_cast<LPARAM
>(this);
668 EnumChildWindows(parent
, HideWindowsCallback
, lparam
);
669 // We reparent the legacy Chrome_RenderWidgetHostHWND window to the global
670 // hidden window on the same lines as Windowed plugin windows.
671 if (legacy_render_widget_host_HWND_
)
672 legacy_render_widget_host_HWND_
->UpdateParent(ui::GetHiddenWindow());
678 if (legacy_render_widget_host_HWND_
)
679 legacy_render_widget_host_HWND_
->Hide();
683 void RenderWidgetHostViewAura::SetSize(const gfx::Size
& size
) {
684 // For a SetSize operation, we don't care what coordinate system the origin
685 // of the window is in, it's only important to make sure that the origin
686 // remains constant after the operation.
687 InternalSetBounds(gfx::Rect(window_
->bounds().origin(), size
));
690 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect
& rect
) {
691 gfx::Point
relative_origin(rect
.origin());
693 // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but
694 // Window::SetBounds() takes parent coordinates, so do the conversion here.
695 aura::Window
* root
= window_
->GetRootWindow();
697 aura::client::ScreenPositionClient
* screen_position_client
=
698 aura::client::GetScreenPositionClient(root
);
699 if (screen_position_client
) {
700 screen_position_client
->ConvertPointFromScreen(
701 window_
->parent(), &relative_origin
);
705 InternalSetBounds(gfx::Rect(relative_origin
, rect
.size()));
708 gfx::Vector2dF
RenderWidgetHostViewAura::GetLastScrollOffset() const {
709 return last_scroll_offset_
;
712 gfx::NativeView
RenderWidgetHostViewAura::GetNativeView() const {
716 gfx::NativeViewId
RenderWidgetHostViewAura::GetNativeViewId() const {
718 aura::WindowTreeHost
* host
= window_
->GetHost();
720 return reinterpret_cast<gfx::NativeViewId
>(host
->GetAcceleratedWidget());
722 return static_cast<gfx::NativeViewId
>(NULL
);
725 gfx::NativeViewAccessible
RenderWidgetHostViewAura::GetNativeViewAccessible() {
727 aura::WindowTreeHost
* host
= window_
->GetHost();
729 return static_cast<gfx::NativeViewAccessible
>(NULL
);
730 BrowserAccessibilityManager
* manager
=
731 host_
->GetOrCreateRootBrowserAccessibilityManager();
733 return manager
->GetRoot()->ToBrowserAccessibilityWin();
737 return static_cast<gfx::NativeViewAccessible
>(NULL
);
740 ui::TextInputClient
* RenderWidgetHostViewAura::GetTextInputClient() {
744 void RenderWidgetHostViewAura::OnSetNeedsBeginFrames(bool needs_begin_frames
) {
745 begin_frame_observer_proxy_
.SetNeedsBeginFrames(needs_begin_frames
);
748 void RenderWidgetHostViewAura::SendBeginFrame(const cc::BeginFrameArgs
& args
) {
749 delegated_frame_host_
->SetVSyncParameters(args
.frame_time
, args
.interval
);
750 host_
->Send(new ViewMsg_BeginFrame(host_
->GetRoutingID(), args
));
753 void RenderWidgetHostViewAura::SetKeyboardFocus() {
756 aura::WindowTreeHost
* host
= window_
->GetHost();
758 ::SetFocus(host
->GetAcceleratedWidget());
761 if (host_
&& set_focus_on_mouse_down_
) {
762 set_focus_on_mouse_down_
= false;
767 RenderFrameHostImpl
* RenderWidgetHostViewAura::GetFocusedFrame() {
768 if (!host_
->IsRenderView())
770 RenderViewHost
* rvh
= RenderViewHost::From(host_
);
771 FrameTreeNode
* focused_frame
=
772 rvh
->GetDelegate()->GetFrameTree()->GetFocusedFrame();
776 return focused_frame
->current_frame_host();
779 bool RenderWidgetHostViewAura::CanRendererHandleEvent(
780 const ui::MouseEvent
* event
,
782 bool selection_popup
) {
784 bool showing_context_menu
= showing_context_menu_
;
785 showing_context_menu_
= false;
788 if (event
->type() == ui::ET_MOUSE_CAPTURE_CHANGED
)
791 if (event
->type() == ui::ET_MOUSE_EXITED
) {
792 if (mouse_locked
|| selection_popup
)
795 // Don't forward the mouse leave message which is received when the context
796 // menu is displayed by the page. This confuses the page and causes state
798 if (showing_context_menu
)
805 // Renderer cannot handle WM_XBUTTON or NC events.
806 switch (event
->native_event().message
) {
809 case WM_XBUTTONDBLCLK
:
810 case WM_NCMOUSELEAVE
:
812 case WM_NCLBUTTONDOWN
:
814 case WM_NCLBUTTONDBLCLK
:
815 case WM_NCRBUTTONDOWN
:
817 case WM_NCRBUTTONDBLCLK
:
818 case WM_NCMBUTTONDOWN
:
820 case WM_NCMBUTTONDBLCLK
:
821 case WM_NCXBUTTONDOWN
:
823 case WM_NCXBUTTONDBLCLK
:
828 #elif defined(USE_X11)
829 // Renderer only supports standard mouse buttons, so ignore programmable
831 switch (event
->type()) {
832 case ui::ET_MOUSE_PRESSED
:
833 case ui::ET_MOUSE_RELEASED
: {
834 const int kAllowedButtons
= ui::EF_LEFT_MOUSE_BUTTON
|
835 ui::EF_MIDDLE_MOUSE_BUTTON
|
836 ui::EF_RIGHT_MOUSE_BUTTON
;
837 return (event
->flags() & kAllowedButtons
) != 0;
846 void RenderWidgetHostViewAura::HandleParentBoundsChanged() {
847 SnapToPhysicalPixelBoundary();
849 if (legacy_render_widget_host_HWND_
) {
850 legacy_render_widget_host_HWND_
->SetBounds(
851 window_
->GetBoundsInRootWindow());
855 host_
->SendScreenRects();
858 void RenderWidgetHostViewAura::ParentHierarchyChanged() {
859 ancestor_window_observer_
.reset(new WindowAncestorObserver(this));
860 // Snap when we receive a hierarchy changed. http://crbug.com/388908.
861 HandleParentBoundsChanged();
864 void RenderWidgetHostViewAura::MovePluginWindows(
865 const std::vector
<WebPluginGeometry
>& plugin_window_moves
) {
867 // We need to clip the rectangle to the tab's viewport, otherwise we will draw
868 // over the browser UI.
869 if (!window_
->GetRootWindow()) {
870 DCHECK(plugin_window_moves
.empty());
873 HWND parent
= window_
->GetHost()->GetAcceleratedWidget();
874 gfx::Rect view_bounds
= window_
->GetBoundsInRootWindow();
875 std::vector
<WebPluginGeometry
> moves
= plugin_window_moves
;
877 gfx::Rect
view_port(view_bounds
.size());
879 for (size_t i
= 0; i
< moves
.size(); ++i
) {
880 gfx::Rect
clip(moves
[i
].clip_rect
);
881 gfx::Vector2d
view_port_offset(
882 moves
[i
].window_rect
.OffsetFromOrigin());
883 clip
.Offset(view_port_offset
);
884 clip
.Intersect(view_port
);
885 clip
.Offset(-view_port_offset
);
886 moves
[i
].clip_rect
= clip
;
888 moves
[i
].window_rect
.Offset(view_bounds
.OffsetFromOrigin());
890 plugin_window_moves_
[moves
[i
].window
] = moves
[i
];
892 // constrained_rects_ are relative to the root window. We want to convert
893 // them to be relative to the plugin window.
894 for (size_t j
= 0; j
< constrained_rects_
.size(); ++j
) {
895 gfx::Rect offset_cutout
= constrained_rects_
[j
];
896 offset_cutout
-= moves
[i
].window_rect
.OffsetFromOrigin();
897 moves
[i
].cutout_rects
.push_back(offset_cutout
);
901 MovePluginWindowsHelper(parent
, moves
);
903 // Make sure each plugin window (or its wrapper if it exists) has a pointer to
905 for (size_t i
= 0; i
< moves
.size(); ++i
) {
906 HWND window
= moves
[i
].window
;
907 if (GetParent(window
) != parent
) {
908 window
= GetParent(window
);
910 if (!GetProp(window
, kWidgetOwnerProperty
))
911 SetProp(window
, kWidgetOwnerProperty
, this);
913 #endif // defined(OS_WIN)
916 void RenderWidgetHostViewAura::Focus() {
917 // Make sure we have a FocusClient before attempting to Focus(). In some
918 // situations we may not yet be in a valid Window hierarchy (such as reloading
919 // after out of memory discarded the tab).
920 aura::client::FocusClient
* client
= aura::client::GetFocusClient(window_
);
925 bool RenderWidgetHostViewAura::HasFocus() const {
926 return window_
->HasFocus();
929 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
930 return delegated_frame_host_
->CanCopyToBitmap();
933 bool RenderWidgetHostViewAura::IsShowing() {
934 return window_
->IsVisible();
937 gfx::Rect
RenderWidgetHostViewAura::GetViewBounds() const {
938 return window_
->GetBoundsInScreen();
941 void RenderWidgetHostViewAura::SetBackgroundColor(SkColor color
) {
942 RenderWidgetHostViewBase::SetBackgroundColor(color
);
943 bool opaque
= GetBackgroundOpaque();
944 host_
->SetBackgroundOpaque(opaque
);
945 window_
->layer()->SetFillsBoundsOpaquely(opaque
);
946 window_
->layer()->SetColor(color
);
949 gfx::Size
RenderWidgetHostViewAura::GetVisibleViewportSize() const {
950 gfx::Rect
requested_rect(GetRequestedRendererSize());
951 requested_rect
.Inset(insets_
);
952 return requested_rect
.size();
955 void RenderWidgetHostViewAura::SetInsets(const gfx::Insets
& insets
) {
956 if (insets
!= insets_
) {
962 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor
& cursor
) {
963 current_cursor_
= cursor
;
964 const gfx::Display display
= gfx::Screen::GetScreenFor(window_
)->
965 GetDisplayNearestWindow(window_
);
966 current_cursor_
.SetDisplayInfo(display
);
967 UpdateCursorIfOverSelf();
970 void RenderWidgetHostViewAura::SetIsLoading(bool is_loading
) {
971 is_loading_
= is_loading
;
972 UpdateCursorIfOverSelf();
975 void RenderWidgetHostViewAura::TextInputStateChanged(
976 const ViewHostMsg_TextInputState_Params
& params
) {
977 if (text_input_type_
!= params
.type
||
978 text_input_mode_
!= params
.mode
||
979 can_compose_inline_
!= params
.can_compose_inline
||
980 text_input_flags_
!= params
.flags
) {
981 text_input_type_
= params
.type
;
982 text_input_mode_
= params
.mode
;
983 can_compose_inline_
= params
.can_compose_inline
;
984 text_input_flags_
= params
.flags
;
985 if (GetInputMethod())
986 GetInputMethod()->OnTextInputTypeChanged(this);
988 if (params
.show_ime_if_needed
&& params
.type
!= ui::TEXT_INPUT_TYPE_NONE
) {
989 if (GetInputMethod())
990 GetInputMethod()->ShowImeIfNeeded();
994 void RenderWidgetHostViewAura::ImeCancelComposition() {
995 if (GetInputMethod())
996 GetInputMethod()->CancelComposition(this);
997 has_composition_text_
= false;
1000 void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
1001 const gfx::Range
& range
,
1002 const std::vector
<gfx::Rect
>& character_bounds
) {
1003 composition_character_bounds_
= character_bounds
;
1006 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status
,
1008 UpdateCursorIfOverSelf();
1012 void RenderWidgetHostViewAura::Destroy() {
1013 // Beware, this function is not called on all destruction paths. It will
1014 // implicitly end up calling ~RenderWidgetHostViewAura though, so all
1015 // destruction/cleanup code should happen there, not here.
1016 in_shutdown_
= true;
1020 void RenderWidgetHostViewAura::SetTooltipText(
1021 const base::string16
& tooltip_text
) {
1022 tooltip_
= tooltip_text
;
1023 aura::Window
* root_window
= window_
->GetRootWindow();
1024 aura::client::TooltipClient
* tooltip_client
=
1025 aura::client::GetTooltipClient(root_window
);
1026 if (tooltip_client
) {
1027 tooltip_client
->UpdateTooltip(window_
);
1028 // Content tooltips should be visible indefinitely.
1029 tooltip_client
->SetTooltipShownTimeout(window_
, 0);
1033 void RenderWidgetHostViewAura::SelectionChanged(const base::string16
& text
,
1035 const gfx::Range
& range
) {
1036 RenderWidgetHostViewBase::SelectionChanged(text
, offset
, range
);
1038 #if defined(USE_X11) && !defined(OS_CHROMEOS)
1039 if (text
.empty() || range
.is_empty())
1041 size_t pos
= range
.GetMin() - offset
;
1042 size_t n
= range
.length();
1044 DCHECK(pos
+ n
<= text
.length()) << "The text can not fully cover range.";
1045 if (pos
>= text
.length()) {
1046 NOTREACHED() << "The text can not cover range.";
1050 // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard.
1051 ui::ScopedClipboardWriter
clipboard_writer(ui::CLIPBOARD_TYPE_SELECTION
);
1052 clipboard_writer
.WriteText(text
.substr(pos
, n
));
1053 #endif // defined(USE_X11) && !defined(OS_CHROMEOS)
1056 gfx::Size
RenderWidgetHostViewAura::GetRequestedRendererSize() const {
1057 return delegated_frame_host_
->GetRequestedRendererSize();
1060 void RenderWidgetHostViewAura::SelectionBoundsChanged(
1061 const ViewHostMsg_SelectionBounds_Params
& params
) {
1062 ui::SelectionBound anchor_bound
, focus_bound
;
1063 anchor_bound
.SetEdge(params
.anchor_rect
.origin(),
1064 params
.anchor_rect
.bottom_left());
1065 focus_bound
.SetEdge(params
.focus_rect
.origin(),
1066 params
.focus_rect
.bottom_left());
1068 if (params
.anchor_rect
== params
.focus_rect
) {
1069 anchor_bound
.set_type(ui::SelectionBound::CENTER
);
1070 focus_bound
.set_type(ui::SelectionBound::CENTER
);
1072 // Whether text is LTR at the anchor handle.
1073 bool anchor_LTR
= params
.anchor_dir
== blink::WebTextDirectionLeftToRight
;
1074 // Whether text is LTR at the focus handle.
1075 bool focus_LTR
= params
.focus_dir
== blink::WebTextDirectionLeftToRight
;
1077 if ((params
.is_anchor_first
&& anchor_LTR
) ||
1078 (!params
.is_anchor_first
&& !anchor_LTR
)) {
1079 anchor_bound
.set_type(ui::SelectionBound::LEFT
);
1081 anchor_bound
.set_type(ui::SelectionBound::RIGHT
);
1083 if ((params
.is_anchor_first
&& focus_LTR
) ||
1084 (!params
.is_anchor_first
&& !focus_LTR
)) {
1085 focus_bound
.set_type(ui::SelectionBound::RIGHT
);
1087 focus_bound
.set_type(ui::SelectionBound::LEFT
);
1091 if (anchor_bound
== selection_anchor_
&& focus_bound
== selection_focus_
)
1094 selection_anchor_
= anchor_bound
;
1095 selection_focus_
= focus_bound
;
1096 if (GetInputMethod())
1097 GetInputMethod()->OnCaretBoundsChanged(this);
1100 void RenderWidgetHostViewAura::CopyFromCompositingSurface(
1101 const gfx::Rect
& src_subrect
,
1102 const gfx::Size
& dst_size
,
1103 ReadbackRequestCallback
& callback
,
1104 const SkColorType preferred_color_type
) {
1105 delegated_frame_host_
->CopyFromCompositingSurface(
1106 src_subrect
, dst_size
, callback
, preferred_color_type
);
1109 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
1110 const gfx::Rect
& src_subrect
,
1111 const scoped_refptr
<media::VideoFrame
>& target
,
1112 const base::Callback
<void(bool)>& callback
) {
1113 delegated_frame_host_
->CopyFromCompositingSurfaceToVideoFrame(
1114 src_subrect
, target
, callback
);
1117 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
1118 return delegated_frame_host_
->CanCopyToVideoFrame();
1121 bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
1125 void RenderWidgetHostViewAura::BeginFrameSubscription(
1126 scoped_ptr
<RenderWidgetHostViewFrameSubscriber
> subscriber
) {
1127 delegated_frame_host_
->BeginFrameSubscription(subscriber
.Pass());
1130 void RenderWidgetHostViewAura::EndFrameSubscription() {
1131 delegated_frame_host_
->EndFrameSubscription();
1135 bool RenderWidgetHostViewAura::UsesNativeWindowFrame() const {
1136 return (legacy_render_widget_host_HWND_
!= NULL
);
1139 void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
1140 const std::vector
<gfx::Rect
>& rects
) {
1141 // Check this before setting constrained_rects_, so that next time they're set
1142 // and we have a root window we don't early return.
1143 if (!window_
->GetHost())
1146 if (rects
== constrained_rects_
)
1149 constrained_rects_
= rects
;
1151 HWND parent
= window_
->GetHost()->GetAcceleratedWidget();
1152 CutoutRectsParams params
;
1153 params
.widget
= this;
1154 params
.cutout_rects
= constrained_rects_
;
1155 params
.geometry
= &plugin_window_moves_
;
1156 LPARAM lparam
= reinterpret_cast<LPARAM
>(¶ms
);
1157 EnumChildWindows(parent
, SetCutoutRectsCallback
, lparam
);
1160 void RenderWidgetHostViewAura::UpdateMouseLockRegion() {
1161 // Clip the cursor if chrome is running on regular desktop.
1162 if (gfx::Screen::GetScreenFor(window_
) == gfx::Screen::GetNativeScreen()) {
1164 gfx::win::DIPToScreenRect(window_
->GetBoundsInScreen()).ToRECT();
1165 ::ClipCursor(&window_rect
);
1169 void RenderWidgetHostViewAura::OnLegacyWindowDestroyed() {
1170 legacy_render_widget_host_HWND_
= NULL
;
1171 legacy_window_destroyed_
= true;
1175 void RenderWidgetHostViewAura::OnSwapCompositorFrame(
1176 uint32 output_surface_id
,
1177 scoped_ptr
<cc::CompositorFrame
> frame
) {
1178 TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
1180 last_scroll_offset_
= frame
->metadata
.root_scroll_offset
;
1181 if (!frame
->delegated_frame_data
)
1183 delegated_frame_host_
->SwapDelegatedFrame(
1184 output_surface_id
, frame
->delegated_frame_data
.Pass(),
1185 frame
->metadata
.device_scale_factor
, frame
->metadata
.latency_info
,
1186 &frame
->metadata
.satisfies_sequences
);
1187 SelectionUpdated(frame
->metadata
.selection
.is_editable
,
1188 frame
->metadata
.selection
.is_empty_text_form_control
,
1189 ConvertSelectionBound(frame
->metadata
.selection
.start
),
1190 ConvertSelectionBound(frame
->metadata
.selection
.end
));
1193 void RenderWidgetHostViewAura::ClearCompositorFrame() {
1194 delegated_frame_host_
->ClearDelegatedFrame();
1197 void RenderWidgetHostViewAura::DidStopFlinging() {
1198 selection_controller_client_
->OnScrollCompleted();
1202 void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
1203 gfx::NativeViewAccessible accessible_parent
) {
1206 gfx::NativeViewId
RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
1208 if (legacy_render_widget_host_HWND_
) {
1209 return reinterpret_cast<gfx::NativeViewId
>(
1210 legacy_render_widget_host_HWND_
->hwnd());
1216 bool RenderWidgetHostViewAura::HasAcceleratedSurface(
1217 const gfx::Size
& desired_size
) {
1218 // Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
1219 // matter what is returned here as GetBackingStore is the only caller of this
1220 // method. TODO(jbates) implement this if other Aura code needs it.
1224 void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo
* results
) {
1225 GetScreenInfoForWindow(results
, window_
->GetRootWindow() ? window_
: NULL
);
1228 bool RenderWidgetHostViewAura::GetScreenColorProfile(
1229 std::vector
<char>* color_profile
) {
1230 DCHECK(color_profile
->empty());
1231 gfx::Rect
bounds(window_
->GetToplevelWindow()->GetBoundsInScreen());
1232 return gfx::GetDisplayColorProfile(bounds
, color_profile
);
1235 gfx::Rect
RenderWidgetHostViewAura::GetBoundsInRootWindow() {
1236 aura::Window
* top_level
= window_
->GetToplevelWindow();
1237 gfx::Rect
bounds(top_level
->GetBoundsInScreen());
1240 // TODO(zturner,iyengar): This will break when we remove support for NPAPI and
1241 // remove the legacy hwnd, so a better fix will need to be decided when that
1243 if (UsesNativeWindowFrame()) {
1244 // aura::Window doesn't take into account non-client area of native windows
1245 // (e.g. HWNDs), so for that case ask Windows directly what the bounds are.
1246 aura::WindowTreeHost
* host
= top_level
->GetHost();
1248 return top_level
->GetBoundsInScreen();
1249 RECT window_rect
= {0};
1250 HWND hwnd
= host
->GetAcceleratedWidget();
1251 ::GetWindowRect(hwnd
, &window_rect
);
1252 bounds
= gfx::Rect(window_rect
);
1254 // Maximized windows are outdented from the work area by the frame thickness
1255 // even though this "frame" is not painted. This confuses code (and people)
1256 // that think of a maximized window as corresponding exactly to the work
1257 // area. Correct for this by subtracting the frame thickness back off.
1258 if (::IsZoomed(hwnd
)) {
1259 bounds
.Inset(GetSystemMetrics(SM_CXSIZEFRAME
),
1260 GetSystemMetrics(SM_CYSIZEFRAME
));
1262 bounds
.Inset(GetSystemMetrics(SM_CXPADDEDBORDER
),
1263 GetSystemMetrics(SM_CXPADDEDBORDER
));
1267 bounds
= gfx::win::ScreenToDIPRect(bounds
);
1273 void RenderWidgetHostViewAura::WheelEventAck(
1274 const blink::WebMouseWheelEvent
& event
,
1275 InputEventAckState ack_result
) {
1276 if (overscroll_controller_
) {
1277 overscroll_controller_
->ReceivedEventACK(
1278 event
, (INPUT_EVENT_ACK_STATE_CONSUMED
== ack_result
));
1282 void RenderWidgetHostViewAura::GestureEventAck(
1283 const blink::WebGestureEvent
& event
,
1284 InputEventAckState ack_result
) {
1285 if (overscroll_controller_
) {
1286 overscroll_controller_
->ReceivedEventACK(
1287 event
, (INPUT_EVENT_ACK_STATE_CONSUMED
== ack_result
));
1291 void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
1292 const TouchEventWithLatencyInfo
& touch
,
1293 InputEventAckState ack_result
) {
1294 ScopedVector
<ui::TouchEvent
> events
;
1295 aura::WindowTreeHost
* host
= window_
->GetHost();
1296 // |host| is NULL during tests.
1300 ui::EventResult result
= (ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
)
1304 blink::WebTouchPoint::State required_state
;
1305 switch (touch
.event
.type
) {
1306 case blink::WebInputEvent::TouchStart
:
1307 required_state
= blink::WebTouchPoint::StatePressed
;
1309 case blink::WebInputEvent::TouchEnd
:
1310 required_state
= blink::WebTouchPoint::StateReleased
;
1312 case blink::WebInputEvent::TouchMove
:
1313 required_state
= blink::WebTouchPoint::StateMoved
;
1315 case blink::WebInputEvent::TouchCancel
:
1316 required_state
= blink::WebTouchPoint::StateCancelled
;
1319 required_state
= blink::WebTouchPoint::StateUndefined
;
1324 // Only send acks for one changed touch point.
1325 bool sent_ack
= false;
1326 for (size_t i
= 0; i
< touch
.event
.touchesLength
; ++i
) {
1327 if (touch
.event
.touches
[i
].state
== required_state
) {
1329 host
->dispatcher()->ProcessedTouchEvent(touch
.event
.uniqueTouchEventId
,
1336 scoped_ptr
<SyntheticGestureTarget
>
1337 RenderWidgetHostViewAura::CreateSyntheticGestureTarget() {
1338 return scoped_ptr
<SyntheticGestureTarget
>(
1339 new SyntheticGestureTargetAura(host_
));
1342 InputEventAckState
RenderWidgetHostViewAura::FilterInputEvent(
1343 const blink::WebInputEvent
& input_event
) {
1344 bool consumed
= false;
1345 if (input_event
.type
== WebInputEvent::GestureFlingStart
) {
1346 const WebGestureEvent
& gesture_event
=
1347 static_cast<const WebGestureEvent
&>(input_event
);
1348 // Zero-velocity touchpad flings are an Aura-specific signal that the
1349 // touchpad scroll has ended, and should not be forwarded to the renderer.
1350 if (gesture_event
.sourceDevice
== blink::WebGestureDeviceTouchpad
&&
1351 !gesture_event
.data
.flingStart
.velocityX
&&
1352 !gesture_event
.data
.flingStart
.velocityY
) {
1357 if (overscroll_controller_
)
1358 consumed
|= overscroll_controller_
->WillHandleEvent(input_event
);
1360 // Touch events should always propagate to the renderer.
1361 if (WebTouchEvent::isTouchEventType(input_event
.type
))
1362 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED
;
1364 // Reporting consumed for a fling suggests that there's now an *active* fling
1365 // that requires both animation and a fling-end notification. However, the
1366 // OverscrollController consumes a fling to stop its propagation; it doesn't
1367 // actually tick a fling animation. Report no consumer to convey this.
1368 if (consumed
&& input_event
.type
== blink::WebInputEvent::GestureFlingStart
)
1369 return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
;
1371 return consumed
? INPUT_EVENT_ACK_STATE_CONSUMED
1372 : INPUT_EVENT_ACK_STATE_NOT_CONSUMED
;
1375 BrowserAccessibilityManager
*
1376 RenderWidgetHostViewAura::CreateBrowserAccessibilityManager(
1377 BrowserAccessibilityDelegate
* delegate
) {
1378 BrowserAccessibilityManager
* manager
= NULL
;
1380 manager
= new BrowserAccessibilityManagerWin(
1381 BrowserAccessibilityManagerWin::GetEmptyDocument(), delegate
);
1383 manager
= BrowserAccessibilityManager::Create(
1384 BrowserAccessibilityManager::GetEmptyDocument(), delegate
);
1389 gfx::AcceleratedWidget
1390 RenderWidgetHostViewAura::AccessibilityGetAcceleratedWidget() {
1392 if (legacy_render_widget_host_HWND_
)
1393 return legacy_render_widget_host_HWND_
->hwnd();
1395 return gfx::kNullAcceleratedWidget
;
1398 gfx::NativeViewAccessible
1399 RenderWidgetHostViewAura::AccessibilityGetNativeViewAccessible() {
1401 if (legacy_render_widget_host_HWND_
)
1402 return legacy_render_widget_host_HWND_
->window_accessible();
1407 gfx::GLSurfaceHandle
RenderWidgetHostViewAura::GetCompositingSurface() {
1408 return ImageTransportFactory::GetInstance()->GetSharedSurfaceHandle();
1411 void RenderWidgetHostViewAura::ShowDisambiguationPopup(
1412 const gfx::Rect
& rect_pixels
,
1413 const SkBitmap
& zoomed_bitmap
) {
1414 RenderViewHostDelegate
* delegate
= NULL
;
1415 if (host_
->IsRenderView())
1416 delegate
= RenderViewHost::From(host_
)->GetDelegate();
1417 // Suppress the link disambiguation popup if the virtual keyboard is currently
1418 // requested, as it doesn't interact well with the keyboard.
1419 if (delegate
&& delegate
->IsVirtualKeyboardRequested())
1422 // |target_rect| is provided in pixels, not DIPs. So we convert it to DIPs
1423 // by scaling it by the inverse of the device scale factor.
1424 gfx::RectF
screen_target_rect_f(rect_pixels
);
1425 screen_target_rect_f
.Scale(1.0f
/ current_device_scale_factor_
);
1426 disambiguation_target_rect_
= gfx::ToEnclosingRect(screen_target_rect_f
);
1428 float scale
= static_cast<float>(zoomed_bitmap
.width()) /
1429 static_cast<float>(rect_pixels
.width());
1430 gfx::Size
zoomed_size(gfx::ToCeiledSize(
1431 gfx::ScaleSize(disambiguation_target_rect_
.size(), scale
)));
1433 // Save of a copy of the |last_scroll_offset_| for comparison when the copy
1434 // callback fires, to ensure that we haven't scrolled.
1435 disambiguation_scroll_offset_
= last_scroll_offset_
;
1437 CopyFromCompositingSurface(
1438 disambiguation_target_rect_
,
1440 base::Bind(&RenderWidgetHostViewAura::DisambiguationPopupRendered
,
1441 weak_ptr_factory_
.GetWeakPtr()),
1445 void RenderWidgetHostViewAura::DisambiguationPopupRendered(
1446 const SkBitmap
& result
,
1447 ReadbackResponse response
) {
1448 if ((response
!= READBACK_SUCCESS
) ||
1449 disambiguation_scroll_offset_
!= last_scroll_offset_
)
1452 // Use RenderViewHostDelegate to get to the WebContentsViewAura, which will
1453 // actually show the disambiguation popup.
1454 RenderViewHostDelegate
* delegate
= NULL
;
1455 if (host_
->IsRenderView())
1456 delegate
= RenderViewHost::From(host_
)->GetDelegate();
1457 RenderViewHostDelegateView
* delegate_view
= NULL
;
1459 delegate_view
= delegate
->GetDelegateView();
1460 if (delegate
->IsVirtualKeyboardRequested())
1463 if (delegate_view
) {
1464 delegate_view
->ShowDisambiguationPopup(
1465 disambiguation_target_rect_
,
1467 base::Bind(&RenderWidgetHostViewAura::ProcessDisambiguationGesture
,
1468 weak_ptr_factory_
.GetWeakPtr()),
1469 base::Bind(&RenderWidgetHostViewAura::ProcessDisambiguationMouse
,
1470 weak_ptr_factory_
.GetWeakPtr()));
1474 void RenderWidgetHostViewAura::HideDisambiguationPopup() {
1475 RenderViewHostDelegate
* delegate
= NULL
;
1476 if (host_
->IsRenderView())
1477 delegate
= RenderViewHost::From(host_
)->GetDelegate();
1478 RenderViewHostDelegateView
* delegate_view
= NULL
;
1480 delegate_view
= delegate
->GetDelegateView();
1482 delegate_view
->HideDisambiguationPopup();
1485 void RenderWidgetHostViewAura::ProcessDisambiguationGesture(
1486 ui::GestureEvent
* event
) {
1487 blink::WebGestureEvent web_gesture
= content::MakeWebGestureEvent(*event
);
1488 // If we fail to make a WebGestureEvent that is a Tap from the provided event,
1489 // don't forward it to Blink.
1490 if (web_gesture
.type
< blink::WebInputEvent::Type::GestureTap
||
1491 web_gesture
.type
> blink::WebInputEvent::Type::GestureTapCancel
)
1494 host_
->ForwardGestureEvent(web_gesture
);
1497 void RenderWidgetHostViewAura::ProcessDisambiguationMouse(
1498 ui::MouseEvent
* event
) {
1499 blink::WebMouseEvent web_mouse
= content::MakeWebMouseEvent(*event
);
1500 host_
->ForwardMouseEvent(web_mouse
);
1503 bool RenderWidgetHostViewAura::LockMouse() {
1504 aura::Window
* root_window
= window_
->GetRootWindow();
1511 mouse_locked_
= true;
1512 #if !defined(OS_WIN)
1513 window_
->SetCapture();
1515 UpdateMouseLockRegion();
1517 aura::client::CursorClient
* cursor_client
=
1518 aura::client::GetCursorClient(root_window
);
1519 if (cursor_client
) {
1520 cursor_client
->HideCursor();
1521 cursor_client
->LockCursor();
1524 if (ShouldMoveToCenter()) {
1525 synthetic_move_sent_
= true;
1526 window_
->MoveCursorTo(gfx::Rect(window_
->bounds().size()).CenterPoint());
1528 tooltip_disabler_
.reset(new aura::client::ScopedTooltipDisabler(root_window
));
1532 void RenderWidgetHostViewAura::UnlockMouse() {
1533 tooltip_disabler_
.reset();
1535 aura::Window
* root_window
= window_
->GetRootWindow();
1536 if (!mouse_locked_
|| !root_window
)
1539 mouse_locked_
= false;
1541 if (window_
->HasCapture())
1542 window_
->ReleaseCapture();
1548 window_
->MoveCursorTo(unlocked_mouse_position_
);
1549 aura::client::CursorClient
* cursor_client
=
1550 aura::client::GetCursorClient(root_window
);
1551 if (cursor_client
) {
1552 cursor_client
->UnlockCursor();
1553 cursor_client
->ShowCursor();
1556 host_
->LostMouseLock();
1559 ////////////////////////////////////////////////////////////////////////////////
1560 // RenderWidgetHostViewAura, ui::TextInputClient implementation:
1561 void RenderWidgetHostViewAura::SetCompositionText(
1562 const ui::CompositionText
& composition
) {
1566 // TODO(suzhe): convert both renderer_host and renderer to use
1567 // ui::CompositionText.
1568 std::vector
<blink::WebCompositionUnderline
> underlines
;
1569 underlines
.reserve(composition
.underlines
.size());
1570 for (std::vector
<ui::CompositionUnderline
>::const_iterator it
=
1571 composition
.underlines
.begin();
1572 it
!= composition
.underlines
.end(); ++it
) {
1573 underlines
.push_back(
1574 blink::WebCompositionUnderline(static_cast<unsigned>(it
->start_offset
),
1575 static_cast<unsigned>(it
->end_offset
),
1578 it
->background_color
));
1581 // TODO(suzhe): due to a bug of webkit, we can't use selection range with
1582 // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
1583 host_
->ImeSetComposition(composition
.text
, underlines
,
1584 composition
.selection
.end(),
1585 composition
.selection
.end());
1587 has_composition_text_
= !composition
.text
.empty();
1590 void RenderWidgetHostViewAura::ConfirmCompositionText() {
1591 if (host_
&& has_composition_text_
) {
1592 host_
->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
1595 has_composition_text_
= false;
1598 void RenderWidgetHostViewAura::ClearCompositionText() {
1599 if (host_
&& has_composition_text_
)
1600 host_
->ImeCancelComposition();
1601 has_composition_text_
= false;
1604 void RenderWidgetHostViewAura::InsertText(const base::string16
& text
) {
1605 DCHECK(text_input_type_
!= ui::TEXT_INPUT_TYPE_NONE
);
1607 host_
->ImeConfirmComposition(text
, gfx::Range::InvalidRange(), false);
1608 has_composition_text_
= false;
1611 void RenderWidgetHostViewAura::InsertChar(base::char16 ch
, int flags
) {
1612 if (popup_child_host_view_
&& popup_child_host_view_
->NeedsInputGrab()) {
1613 popup_child_host_view_
->InsertChar(ch
, flags
);
1617 // Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547
1618 if (host_
&& (accept_return_character_
|| ch
!= ui::VKEY_RETURN
)) {
1619 double now
= ui::EventTimeForNow().InSecondsF();
1620 // Send a blink::WebInputEvent::Char event to |host_|.
1621 NativeWebKeyboardEvent
webkit_event(ui::ET_KEY_PRESSED
,
1626 ForwardKeyboardEvent(webkit_event
);
1630 ui::TextInputType
RenderWidgetHostViewAura::GetTextInputType() const {
1631 return text_input_type_
;
1634 ui::TextInputMode
RenderWidgetHostViewAura::GetTextInputMode() const {
1635 return text_input_mode_
;
1638 int RenderWidgetHostViewAura::GetTextInputFlags() const {
1639 return text_input_flags_
;
1642 bool RenderWidgetHostViewAura::CanComposeInline() const {
1643 return can_compose_inline_
;
1646 gfx::Rect
RenderWidgetHostViewAura::ConvertRectToScreen(
1647 const gfx::Rect
& rect
) const {
1648 gfx::Point origin
= rect
.origin();
1649 gfx::Point end
= gfx::Point(rect
.right(), rect
.bottom());
1651 aura::Window
* root_window
= window_
->GetRootWindow();
1654 aura::client::ScreenPositionClient
* screen_position_client
=
1655 aura::client::GetScreenPositionClient(root_window
);
1656 if (!screen_position_client
)
1658 screen_position_client
->ConvertPointToScreen(window_
, &origin
);
1659 screen_position_client
->ConvertPointToScreen(window_
, &end
);
1660 return gfx::Rect(origin
.x(),
1662 end
.x() - origin
.x(),
1663 end
.y() - origin
.y());
1666 gfx::Rect
RenderWidgetHostViewAura::ConvertRectFromScreen(
1667 const gfx::Rect
& rect
) const {
1668 gfx::Point origin
= rect
.origin();
1669 gfx::Point end
= gfx::Point(rect
.right(), rect
.bottom());
1671 aura::Window
* root_window
= window_
->GetRootWindow();
1673 aura::client::ScreenPositionClient
* screen_position_client
=
1674 aura::client::GetScreenPositionClient(root_window
);
1675 screen_position_client
->ConvertPointFromScreen(window_
, &origin
);
1676 screen_position_client
->ConvertPointFromScreen(window_
, &end
);
1677 return gfx::Rect(origin
.x(),
1679 end
.x() - origin
.x(),
1680 end
.y() - origin
.y());
1686 gfx::Rect
RenderWidgetHostViewAura::GetCaretBounds() const {
1687 return ConvertRectToScreen(
1688 ui::RectBetweenSelectionBounds(selection_anchor_
, selection_focus_
));
1691 bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(
1693 gfx::Rect
* rect
) const {
1695 if (index
>= composition_character_bounds_
.size())
1697 *rect
= ConvertRectToScreen(composition_character_bounds_
[index
]);
1701 bool RenderWidgetHostViewAura::HasCompositionText() const {
1702 return has_composition_text_
;
1705 bool RenderWidgetHostViewAura::GetTextRange(gfx::Range
* range
) const {
1706 range
->set_start(selection_text_offset_
);
1707 range
->set_end(selection_text_offset_
+ selection_text_
.length());
1711 bool RenderWidgetHostViewAura::GetCompositionTextRange(
1712 gfx::Range
* range
) const {
1713 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1718 bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range
* range
) const {
1719 range
->set_start(selection_range_
.start());
1720 range
->set_end(selection_range_
.end());
1724 bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range
& range
) {
1725 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1730 bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range
& range
) {
1731 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1736 bool RenderWidgetHostViewAura::GetTextFromRange(
1737 const gfx::Range
& range
,
1738 base::string16
* text
) const {
1739 gfx::Range
selection_text_range(selection_text_offset_
,
1740 selection_text_offset_
+ selection_text_
.length());
1742 if (!selection_text_range
.Contains(range
)) {
1746 if (selection_text_range
.EqualsIgnoringDirection(range
)) {
1747 // Avoid calling substr whose performance is low.
1748 *text
= selection_text_
;
1750 *text
= selection_text_
.substr(
1751 range
.GetMin() - selection_text_offset_
,
1757 void RenderWidgetHostViewAura::OnInputMethodChanged() {
1761 // TODO(suzhe): implement the newly added “locale” property of HTML DOM
1765 bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
1766 base::i18n::TextDirection direction
) {
1769 host_
->UpdateTextDirection(
1770 direction
== base::i18n::RIGHT_TO_LEFT
?
1771 blink::WebTextDirectionRightToLeft
:
1772 blink::WebTextDirectionLeftToRight
);
1773 host_
->NotifyTextDirection();
1777 void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
1778 size_t before
, size_t after
) {
1779 RenderFrameHostImpl
* rfh
= GetFocusedFrame();
1781 rfh
->ExtendSelectionAndDelete(before
, after
);
1784 void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect
& rect
) {
1785 gfx::Rect
intersected_rect(
1786 gfx::IntersectRects(rect
, window_
->GetBoundsInScreen()));
1788 if (intersected_rect
.IsEmpty())
1791 host_
->ScrollFocusedEditableNodeIntoRect(
1792 ConvertRectFromScreen(intersected_rect
));
1795 bool RenderWidgetHostViewAura::IsEditCommandEnabled(int command_id
) {
1799 void RenderWidgetHostViewAura::SetEditCommandForNextKeyEvent(int command_id
) {
1802 ////////////////////////////////////////////////////////////////////////////////
1803 // RenderWidgetHostViewAura, gfx::DisplayObserver implementation:
1805 void RenderWidgetHostViewAura::OnDisplayAdded(
1806 const gfx::Display
& new_display
) {
1809 void RenderWidgetHostViewAura::OnDisplayRemoved(
1810 const gfx::Display
& old_display
) {
1813 void RenderWidgetHostViewAura::OnDisplayMetricsChanged(
1814 const gfx::Display
& display
, uint32_t metrics
) {
1815 // The screen info should be updated regardless of the metric change.
1816 gfx::Screen
* screen
= gfx::Screen::GetScreenFor(window_
);
1817 if (display
.id() == screen
->GetDisplayNearestWindow(window_
).id()) {
1818 UpdateScreenInfo(window_
);
1819 current_cursor_
.SetDisplayInfo(display
);
1820 UpdateCursorIfOverSelf();
1824 ////////////////////////////////////////////////////////////////////////////////
1825 // RenderWidgetHostViewAura, aura::WindowDelegate implementation:
1827 gfx::Size
RenderWidgetHostViewAura::GetMinimumSize() const {
1831 gfx::Size
RenderWidgetHostViewAura::GetMaximumSize() const {
1835 void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect
& old_bounds
,
1836 const gfx::Rect
& new_bounds
) {
1837 base::AutoReset
<bool> in_bounds_changed(&in_bounds_changed_
, true);
1838 // We care about this whenever RenderWidgetHostViewAura is not owned by a
1839 // WebContentsViewAura since changes to the Window's bounds need to be
1840 // messaged to the renderer. WebContentsViewAura invokes SetSize() or
1841 // SetBounds() itself. No matter how we got here, any redundant calls are
1843 SetSize(new_bounds
.size());
1845 if (GetInputMethod())
1846 GetInputMethod()->OnCaretBoundsChanged(this);
1849 gfx::NativeCursor
RenderWidgetHostViewAura::GetCursor(const gfx::Point
& point
) {
1851 return ui::kCursorNone
;
1852 return current_cursor_
.GetNativeCursor();
1855 int RenderWidgetHostViewAura::GetNonClientComponent(
1856 const gfx::Point
& point
) const {
1860 bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
1861 aura::Window
* child
,
1862 const gfx::Point
& location
) {
1866 bool RenderWidgetHostViewAura::CanFocus() {
1867 return popup_type_
== blink::WebPopupTypeNone
;
1870 void RenderWidgetHostViewAura::OnCaptureLost() {
1871 host_
->LostCapture();
1874 void RenderWidgetHostViewAura::OnPaint(const ui::PaintContext
& context
) {
1878 void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
1879 float device_scale_factor
) {
1880 if (!host_
|| !window_
->GetRootWindow())
1883 UpdateScreenInfo(window_
);
1885 const gfx::Display display
= gfx::Screen::GetScreenFor(window_
)->
1886 GetDisplayNearestWindow(window_
);
1887 DCHECK_EQ(device_scale_factor
, display
.device_scale_factor());
1888 current_cursor_
.SetDisplayInfo(display
);
1889 SnapToPhysicalPixelBoundary();
1892 void RenderWidgetHostViewAura::OnWindowDestroying(aura::Window
* window
) {
1895 // If the tab was hidden and it's closed, host_->is_hidden would have been
1896 // reset to false in RenderWidgetHostImpl::RendererExited.
1897 if (!window_
->GetRootWindow() || host_
->is_hidden()) {
1898 parent
= ui::GetHiddenWindow();
1900 parent
= window_
->GetHost()->GetAcceleratedWidget();
1902 LPARAM lparam
= reinterpret_cast<LPARAM
>(this);
1903 EnumChildWindows(parent
, WindowDestroyingCallback
, lparam
);
1905 // The LegacyRenderWidgetHostHWND instance is destroyed when its window is
1906 // destroyed. Normally we control when that happens via the Destroy call
1907 // in the dtor. However there may be cases where the window is destroyed
1908 // by Windows, i.e. the parent window is destroyed before the
1909 // RenderWidgetHostViewAura instance goes away etc. To avoid that we
1910 // destroy the LegacyRenderWidgetHostHWND instance here.
1911 if (legacy_render_widget_host_HWND_
) {
1912 legacy_render_widget_host_HWND_
->set_host(NULL
);
1913 legacy_render_widget_host_HWND_
->Destroy();
1914 // The Destroy call above will delete the LegacyRenderWidgetHostHWND
1916 legacy_render_widget_host_HWND_
= NULL
;
1920 // Make sure that the input method no longer references to this object before
1921 // this object is removed from the root window (i.e. this object loses access
1922 // to the input method).
1923 ui::InputMethod
* input_method
= GetInputMethod();
1925 input_method
->DetachTextInputClient(this);
1927 if (overscroll_controller_
)
1928 overscroll_controller_
->Reset();
1931 void RenderWidgetHostViewAura::OnWindowDestroyed(aura::Window
* window
) {
1932 // Ask the RWH to drop reference to us.
1933 if (!is_guest_view_hack_
)
1934 host_
->ViewDestroyed();
1939 void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible
) {
1942 bool RenderWidgetHostViewAura::HasHitTestMask() const {
1946 void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path
* mask
) const {
1949 ////////////////////////////////////////////////////////////////////////////////
1950 // RenderWidgetHostViewAura, ui::EventHandler implementation:
1952 void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent
* event
) {
1953 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent");
1955 if (popup_child_host_view_
&& popup_child_host_view_
->NeedsInputGrab()) {
1956 popup_child_host_view_
->OnKeyEvent(event
);
1957 if (event
->handled())
1961 // We need to handle the Escape key for Pepper Flash.
1962 if (is_fullscreen_
&& event
->key_code() == ui::VKEY_ESCAPE
) {
1963 // Focus the window we were created from.
1964 if (host_tracker_
.get() && !host_tracker_
->windows().empty()) {
1965 aura::Window
* host
= *(host_tracker_
->windows().begin());
1966 aura::client::FocusClient
* client
= aura::client::GetFocusClient(host
);
1968 // Calling host->Focus() may delete |this|. We create a local observer
1969 // for that. In that case we exit without further access to any members.
1970 aura::WindowTracker tracker
;
1971 aura::Window
* window
= window_
;
1972 tracker
.Add(window
);
1974 if (!tracker
.Contains(window
)) {
1975 event
->SetHandled();
1982 if (event
->key_code() == ui::VKEY_RETURN
) {
1983 // Do not forward return key release events if no press event was handled.
1984 if (event
->type() == ui::ET_KEY_RELEASED
&& !accept_return_character_
)
1986 // Accept return key character events between press and release events.
1987 accept_return_character_
= event
->type() == ui::ET_KEY_PRESSED
;
1990 // We don't have to communicate with an input method here.
1991 NativeWebKeyboardEvent
webkit_event(*event
);
1992 ForwardKeyboardEvent(webkit_event
);
1994 event
->SetHandled();
1997 void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent
* event
) {
1998 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
2000 if (mouse_locked_
) {
2001 aura::client::CursorClient
* cursor_client
=
2002 aura::client::GetCursorClient(window_
->GetRootWindow());
2003 DCHECK(!cursor_client
|| !cursor_client
->IsCursorVisible());
2005 if (event
->type() == ui::ET_MOUSEWHEEL
) {
2006 blink::WebMouseWheelEvent mouse_wheel_event
=
2007 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent
&>(*event
));
2008 if (mouse_wheel_event
.deltaX
!= 0 || mouse_wheel_event
.deltaY
!= 0)
2009 host_
->ForwardWheelEvent(mouse_wheel_event
);
2013 gfx::Point
center(gfx::Rect(window_
->bounds().size()).CenterPoint());
2015 // If we receive non client mouse messages while we are in the locked state
2016 // it probably means that the mouse left the borders of our window and
2017 // needs to be moved back to the center.
2018 if (event
->flags() & ui::EF_IS_NON_CLIENT
) {
2019 synthetic_move_sent_
= true;
2020 window_
->MoveCursorTo(center
);
2024 blink::WebMouseEvent mouse_event
= MakeWebMouseEvent(*event
);
2026 bool is_move_to_center_event
= (event
->type() == ui::ET_MOUSE_MOVED
||
2027 event
->type() == ui::ET_MOUSE_DRAGGED
) &&
2028 mouse_event
.x
== center
.x() && mouse_event
.y
== center
.y();
2030 // For fractional scale factors, the conversion from pixels to dip and
2031 // vice versa could result in off by 1 or 2 errors which hurts us because
2032 // we want to avoid sending the artificial move to center event to the
2033 // renderer. Sending the move to center to the renderer cause the cursor
2034 // to bounce around the center of the screen leading to the lock operation
2035 // not working correctly.
2036 // Workaround is to treat a mouse move or drag event off by at most 2 px
2037 // from the center as a move to center event.
2038 if (synthetic_move_sent_
&&
2039 IsFractionalScaleFactor(current_device_scale_factor_
)) {
2040 if (event
->type() == ui::ET_MOUSE_MOVED
||
2041 event
->type() == ui::ET_MOUSE_DRAGGED
) {
2042 if ((abs(mouse_event
.x
- center
.x()) <= 2) &&
2043 (abs(mouse_event
.y
- center
.y()) <= 2)) {
2044 is_move_to_center_event
= true;
2049 ModifyEventMovementAndCoords(&mouse_event
);
2051 bool should_not_forward
= is_move_to_center_event
&& synthetic_move_sent_
;
2052 if (should_not_forward
) {
2053 synthetic_move_sent_
= false;
2055 // Check if the mouse has reached the border and needs to be centered.
2056 if (ShouldMoveToCenter()) {
2057 synthetic_move_sent_
= true;
2058 window_
->MoveCursorTo(center
);
2060 bool is_selection_popup
= popup_child_host_view_
&&
2061 popup_child_host_view_
->NeedsInputGrab();
2062 // Forward event to renderer.
2063 if (CanRendererHandleEvent(event
, mouse_locked_
, is_selection_popup
) &&
2064 !(event
->flags() & ui::EF_FROM_TOUCH
)) {
2065 host_
->ForwardMouseEvent(mouse_event
);
2066 // Ensure that we get keyboard focus on mouse down as a plugin window
2067 // may have grabbed keyboard focus.
2068 if (event
->type() == ui::ET_MOUSE_PRESSED
)
2075 // As the overscroll is handled during scroll events from the trackpad, the
2076 // RWHVA window is transformed by the overscroll controller. This transform
2077 // triggers a synthetic mouse-move event to be generated (by the aura
2078 // RootWindow). But this event interferes with the overscroll gesture. So,
2079 // ignore such synthetic mouse-move events if an overscroll gesture is in
2081 if (overscroll_controller_
&&
2082 overscroll_controller_
->overscroll_mode() != OVERSCROLL_NONE
&&
2083 event
->flags() & ui::EF_IS_SYNTHESIZED
&&
2084 (event
->type() == ui::ET_MOUSE_ENTERED
||
2085 event
->type() == ui::ET_MOUSE_EXITED
||
2086 event
->type() == ui::ET_MOUSE_MOVED
)) {
2087 event
->StopPropagation();
2091 if (event
->type() == ui::ET_MOUSEWHEEL
) {
2093 // We get mouse wheel/scroll messages even if we are not in the foreground.
2094 // So here we check if we have any owned popup windows in the foreground and
2096 aura::WindowTreeHost
* host
= window_
->GetHost();
2098 HWND parent
= host
->GetAcceleratedWidget();
2099 HWND toplevel_hwnd
= ::GetAncestor(parent
, GA_ROOT
);
2100 EnumThreadWindows(GetCurrentThreadId(),
2102 reinterpret_cast<LPARAM
>(toplevel_hwnd
));
2105 // The Disambiguation popup does not parent itself from this window, so we
2106 // manually dismiss it.
2107 HideDisambiguationPopup();
2109 blink::WebMouseWheelEvent mouse_wheel_event
=
2110 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent
&>(*event
));
2111 if (mouse_wheel_event
.deltaX
!= 0 || mouse_wheel_event
.deltaY
!= 0) {
2112 if (host_
->delegate() && host_
->delegate()->GetInputEventRouter()) {
2113 host_
->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
2114 this, &mouse_wheel_event
);
2116 ProcessMouseWheelEvent(mouse_wheel_event
);
2120 bool is_selection_popup
=
2121 popup_child_host_view_
&& popup_child_host_view_
->NeedsInputGrab();
2122 if (CanRendererHandleEvent(event
, mouse_locked_
, is_selection_popup
) &&
2123 !(event
->flags() & ui::EF_FROM_TOUCH
)) {
2124 // Confirm existing composition text on mouse press, to make sure
2125 // the input caret won't be moved with an ongoing composition text.
2126 if (event
->type() == ui::ET_MOUSE_PRESSED
)
2127 FinishImeCompositionSession();
2129 blink::WebMouseEvent mouse_event
= MakeWebMouseEvent(*event
);
2130 ModifyEventMovementAndCoords(&mouse_event
);
2131 if (host_
->delegate() && host_
->delegate()->GetInputEventRouter()) {
2132 host_
->delegate()->GetInputEventRouter()->RouteMouseEvent(this,
2135 ProcessMouseEvent(mouse_event
);
2138 // Ensure that we get keyboard focus on mouse down as a plugin window may
2139 // have grabbed keyboard focus.
2140 if (event
->type() == ui::ET_MOUSE_PRESSED
)
2145 switch (event
->type()) {
2146 case ui::ET_MOUSE_PRESSED
:
2147 window_
->SetCapture();
2149 case ui::ET_MOUSE_RELEASED
:
2150 if (!NeedsMouseCapture())
2151 window_
->ReleaseCapture();
2157 // Needed to propagate mouse event to |window_->parent()->delegate()|, but
2158 // note that it might be something other than a WebContentsViewAura instance.
2159 // TODO(pkotwicz): Find a better way of doing this.
2160 // In fullscreen mode which is typically used by flash, don't forward
2161 // the mouse events to the parent. The renderer and the plugin process
2162 // handle these events.
2163 if (!is_fullscreen_
&& window_
->parent() && window_
->parent()->delegate() &&
2164 !(event
->flags() & ui::EF_FROM_TOUCH
)) {
2165 event
->ConvertLocationToTarget(window_
, window_
->parent());
2166 window_
->parent()->delegate()->OnMouseEvent(event
);
2169 if (!IsXButtonUpEvent(event
))
2170 event
->SetHandled();
2173 uint32_t RenderWidgetHostViewAura::SurfaceIdNamespaceAtPoint(
2174 const gfx::Point
& point
,
2175 gfx::Point
* transformed_point
) {
2177 delegated_frame_host_
->SurfaceIdAtPoint(point
, transformed_point
);
2178 // It is possible that the renderer has not yet produced a surface, in which
2179 // case we return our current namespace.
2181 return GetSurfaceIdNamespace();
2182 return cc::SurfaceIdAllocator::NamespaceForId(id
);
2185 void RenderWidgetHostViewAura::ProcessMouseEvent(
2186 const blink::WebMouseEvent
& event
) {
2187 host_
->ForwardMouseEvent(event
);
2190 void RenderWidgetHostViewAura::ProcessMouseWheelEvent(
2191 const blink::WebMouseWheelEvent
& event
) {
2192 host_
->ForwardWheelEvent(event
);
2195 void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent
* event
) {
2196 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
2198 if (event
->type() == ui::ET_SCROLL
) {
2199 #if !defined(OS_WIN)
2201 // Investigate if this is true for Windows 8 Metro ASH as well.
2202 if (event
->finger_count() != 2)
2205 blink::WebGestureEvent gesture_event
=
2206 MakeWebGestureEventFlingCancel();
2207 host_
->ForwardGestureEvent(gesture_event
);
2208 blink::WebMouseWheelEvent mouse_wheel_event
=
2209 MakeWebMouseWheelEvent(*event
);
2210 host_
->ForwardWheelEvent(mouse_wheel_event
);
2211 RecordAction(base::UserMetricsAction("TrackpadScroll"));
2212 } else if (event
->type() == ui::ET_SCROLL_FLING_START
||
2213 event
->type() == ui::ET_SCROLL_FLING_CANCEL
) {
2214 blink::WebGestureEvent gesture_event
= MakeWebGestureEvent(*event
);
2215 host_
->ForwardGestureEvent(gesture_event
);
2216 if (event
->type() == ui::ET_SCROLL_FLING_START
)
2217 RecordAction(base::UserMetricsAction("TrackpadScrollFling"));
2220 event
->SetHandled();
2223 void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent
* event
) {
2224 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent");
2226 bool had_no_pointer
= !pointer_state_
.GetPointerCount();
2228 // Update the touch event first.
2229 if (!pointer_state_
.OnTouch(*event
)) {
2230 event
->StopPropagation();
2234 blink::WebTouchEvent touch_event
;
2235 bool handled
= selection_controller_
->WillHandleTouchEvent(pointer_state_
);
2237 event
->SetHandled();
2239 touch_event
= ui::CreateWebTouchEventFromMotionEvent(
2240 pointer_state_
, event
->may_cause_scrolling());
2242 pointer_state_
.CleanupRemovedTouchPoints(*event
);
2248 selection_controller_client_
->OnTouchDown();
2249 if (!pointer_state_
.GetPointerCount())
2250 selection_controller_client_
->OnTouchUp();
2252 // It is important to always mark events as being handled asynchronously when
2253 // they are forwarded. This ensures that the current event does not get
2254 // processed by the gesture recognizer before events currently awaiting
2255 // dispatch in the touch queue.
2256 event
->DisableSynchronousHandling();
2258 // Set unchanged touch point to StateStationary for touchmove and
2259 // touchcancel to make sure only send one ack per WebTouchEvent.
2260 MarkUnchangedTouchPointsAsStationary(&touch_event
, event
->touch_id());
2261 host_
->ForwardTouchEventWithLatencyInfo(touch_event
, *event
->latency());
2264 void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent
* event
) {
2265 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent");
2267 if ((event
->type() == ui::ET_GESTURE_PINCH_BEGIN
||
2268 event
->type() == ui::ET_GESTURE_PINCH_UPDATE
||
2269 event
->type() == ui::ET_GESTURE_PINCH_END
) && !pinch_zoom_enabled_
) {
2270 event
->SetHandled();
2274 HandleGestureForTouchSelection(event
);
2275 if (event
->handled())
2278 // Confirm existing composition text on TAP gesture, to make sure the input
2279 // caret won't be moved with an ongoing composition text.
2280 if (event
->type() == ui::ET_GESTURE_TAP
)
2281 FinishImeCompositionSession();
2283 blink::WebGestureEvent gesture
= MakeWebGestureEvent(*event
);
2284 if (event
->type() == ui::ET_GESTURE_TAP_DOWN
) {
2285 // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
2286 // event to stop any in-progress flings.
2287 blink::WebGestureEvent fling_cancel
= gesture
;
2288 fling_cancel
.type
= blink::WebInputEvent::GestureFlingCancel
;
2289 fling_cancel
.sourceDevice
= blink::WebGestureDeviceTouchscreen
;
2290 host_
->ForwardGestureEvent(fling_cancel
);
2293 if (gesture
.type
!= blink::WebInputEvent::Undefined
) {
2294 host_
->ForwardGestureEventWithLatencyInfo(gesture
, *event
->latency());
2296 if (event
->type() == ui::ET_GESTURE_SCROLL_BEGIN
||
2297 event
->type() == ui::ET_GESTURE_SCROLL_UPDATE
||
2298 event
->type() == ui::ET_GESTURE_SCROLL_END
) {
2299 RecordAction(base::UserMetricsAction("TouchscreenScroll"));
2300 } else if (event
->type() == ui::ET_SCROLL_FLING_START
) {
2301 RecordAction(base::UserMetricsAction("TouchscreenScrollFling"));
2305 // If a gesture is not processed by the webpage, then WebKit processes it
2306 // (e.g. generates synthetic mouse events).
2307 event
->SetHandled();
2310 ////////////////////////////////////////////////////////////////////////////////
2311 // RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation:
2313 bool RenderWidgetHostViewAura::ShouldActivate() const {
2314 aura::WindowTreeHost
* host
= window_
->GetHost();
2317 const ui::Event
* event
= host
->dispatcher()->current_event();
2320 return is_fullscreen_
;
2323 ////////////////////////////////////////////////////////////////////////////////
2324 // RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation:
2326 void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible
) {
2327 NotifyRendererOfCursorVisibilityState(is_visible
);
2330 ////////////////////////////////////////////////////////////////////////////////
2331 // RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation:
2333 void RenderWidgetHostViewAura::OnWindowFocused(aura::Window
* gained_focus
,
2334 aura::Window
* lost_focus
) {
2335 DCHECK(window_
== gained_focus
|| window_
== lost_focus
);
2336 if (window_
== gained_focus
) {
2337 // We need to honor input bypass if the associated tab is does not want
2338 // input. This gives the current focused window a chance to be the text
2339 // input client and handle events.
2340 if (host_
->ignore_input_events())
2344 host_
->SetActive(true);
2346 ui::InputMethod
* input_method
= GetInputMethod();
2348 // Ask the system-wide IME to send all TextInputClient messages to |this|
2350 input_method
->SetFocusedTextInputClient(this);
2352 // Often the application can set focus to the view in response to a key
2353 // down. However the following char event shouldn't be sent to the web
2355 host_
->SuppressNextCharEvents();
2358 BrowserAccessibilityManager
* manager
=
2359 host_
->GetRootBrowserAccessibilityManager();
2361 manager
->OnWindowFocused();
2362 } else if (window_
== lost_focus
) {
2363 host_
->SetActive(false);
2366 DetachFromInputMethod();
2368 selection_controller_
->HideAndDisallowShowingAutomatically();
2370 if (overscroll_controller_
)
2371 overscroll_controller_
->Cancel();
2373 BrowserAccessibilityManager
* manager
=
2374 host_
->GetRootBrowserAccessibilityManager();
2376 manager
->OnWindowBlurred();
2378 // If we lose the focus while fullscreen, close the window; Pepper Flash
2379 // won't do it for us (unlike NPAPI Flash). However, we do not close the
2380 // window if we lose the focus to a window on another display.
2381 gfx::Screen
* screen
= gfx::Screen::GetScreenFor(window_
);
2382 bool focusing_other_display
=
2383 gained_focus
&& screen
->GetNumDisplays() > 1 &&
2384 (screen
->GetDisplayNearestWindow(window_
).id() !=
2385 screen
->GetDisplayNearestWindow(gained_focus
).id());
2386 if (is_fullscreen_
&& !in_shutdown_
&& !focusing_other_display
) {
2388 // On Windows, if we are switching to a non Aura Window on a different
2389 // screen we should not close the fullscreen window.
2390 if (!gained_focus
) {
2392 ::GetCursorPos(&point
);
2393 if (screen
->GetDisplayNearestWindow(window_
).id() !=
2394 screen
->GetDisplayNearestPoint(gfx::Point(point
)).id())
2402 // Close the child popup window if we lose focus (e.g. due to a JS alert or
2403 // system modal dialog). This is particularly important if
2404 // |popup_child_host_view_| has mouse capture.
2405 if (popup_child_host_view_
)
2406 popup_child_host_view_
->Shutdown();
2410 ////////////////////////////////////////////////////////////////////////////////
2411 // RenderWidgetHostViewAura, aura::WindowTreeHostObserver implementation:
2413 void RenderWidgetHostViewAura::OnHostMoved(const aura::WindowTreeHost
* host
,
2414 const gfx::Point
& new_origin
) {
2415 TRACE_EVENT1("ui", "RenderWidgetHostViewAura::OnHostMoved",
2416 "new_origin", new_origin
.ToString());
2418 UpdateScreenInfo(window_
);
2421 ////////////////////////////////////////////////////////////////////////////////
2422 // RenderWidgetHostViewAura, private:
2424 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
2425 selection_controller_
.reset();
2426 selection_controller_client_
.reset();
2428 if (UseSurfacesEnabled() && host_
->delegate() &&
2429 host_
->delegate()->GetInputEventRouter()) {
2430 host_
->delegate()->GetInputEventRouter()->RemoveSurfaceIdNamespaceOwner(
2431 GetSurfaceIdNamespace());
2433 delegated_frame_host_
.reset();
2434 window_observer_
.reset();
2435 if (window_
->GetHost())
2436 window_
->GetHost()->RemoveObserver(this);
2438 if (popup_parent_host_view_
) {
2439 DCHECK(popup_parent_host_view_
->popup_child_host_view_
== NULL
||
2440 popup_parent_host_view_
->popup_child_host_view_
== this);
2441 popup_parent_host_view_
->popup_child_host_view_
= NULL
;
2443 if (popup_child_host_view_
) {
2444 DCHECK(popup_child_host_view_
->popup_parent_host_view_
== NULL
||
2445 popup_child_host_view_
->popup_parent_host_view_
== this);
2446 popup_child_host_view_
->popup_parent_host_view_
= NULL
;
2448 event_filter_for_popup_exit_
.reset();
2449 aura::client::SetTooltipText(window_
, NULL
);
2450 gfx::Screen::GetScreenFor(window_
)->RemoveObserver(this);
2452 // This call is usually no-op since |this| object is already removed from the
2453 // Aura root window and we don't have a way to get an input method object
2454 // associated with the window, but just in case.
2455 DetachFromInputMethod();
2458 // The LegacyRenderWidgetHostHWND window should have been destroyed in
2459 // RenderWidgetHostViewAura::OnWindowDestroying and the pointer should
2461 DCHECK(!legacy_render_widget_host_HWND_
);
2465 void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
2466 if (host_
->GetProcess()->FastShutdownStarted())
2469 aura::Window
* root_window
= window_
->GetRootWindow();
2473 gfx::Point root_window_point
=
2474 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
2475 aura::client::ScreenPositionClient
* screen_position_client
=
2476 aura::client::GetScreenPositionClient(root_window
);
2477 if (screen_position_client
) {
2478 screen_position_client
->ConvertPointFromScreen(
2479 root_window
, &root_window_point
);
2482 if (root_window
->GetEventHandlerForPoint(root_window_point
) != window_
)
2485 gfx::NativeCursor cursor
= current_cursor_
.GetNativeCursor();
2486 // Do not show loading cursor when the cursor is currently hidden.
2487 if (is_loading_
&& cursor
!= ui::kCursorNone
)
2488 cursor
= ui::kCursorPointer
;
2490 aura::client::CursorClient
* cursor_client
=
2491 aura::client::GetCursorClient(root_window
);
2492 if (cursor_client
) {
2493 cursor_client
->SetCursor(cursor
);
2497 ui::InputMethod
* RenderWidgetHostViewAura::GetInputMethod() const {
2498 aura::Window
* root_window
= window_
->GetRootWindow();
2501 return root_window
->GetHost()->GetInputMethod();
2504 void RenderWidgetHostViewAura::Shutdown() {
2505 if (!in_shutdown_
) {
2506 in_shutdown_
= true;
2511 bool RenderWidgetHostViewAura::NeedsInputGrab() {
2512 return popup_type_
== blink::WebPopupTypePage
;
2515 bool RenderWidgetHostViewAura::NeedsMouseCapture() {
2516 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2517 return NeedsInputGrab();
2522 void RenderWidgetHostViewAura::FinishImeCompositionSession() {
2523 if (!has_composition_text_
)
2526 host_
->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
2529 ImeCancelComposition();
2532 void RenderWidgetHostViewAura::ModifyEventMovementAndCoords(
2533 blink::WebMouseEvent
* event
) {
2534 // If the mouse has just entered, we must report zero movementX/Y. Hence we
2535 // reset any global_mouse_position set previously.
2536 if (event
->type
== blink::WebInputEvent::MouseEnter
||
2537 event
->type
== blink::WebInputEvent::MouseLeave
)
2538 global_mouse_position_
.SetPoint(event
->globalX
, event
->globalY
);
2540 // Movement is computed by taking the difference of the new cursor position
2541 // and the previous. Under mouse lock the cursor will be warped back to the
2542 // center so that we are not limited by clipping boundaries.
2543 // We do not measure movement as the delta from cursor to center because
2544 // we may receive more mouse movement events before our warp has taken
2546 event
->movementX
= event
->globalX
- global_mouse_position_
.x();
2547 event
->movementY
= event
->globalY
- global_mouse_position_
.y();
2549 global_mouse_position_
.SetPoint(event
->globalX
, event
->globalY
);
2551 // Under mouse lock, coordinates of mouse are locked to what they were when
2552 // mouse lock was entered.
2553 if (mouse_locked_
) {
2554 event
->x
= unlocked_mouse_position_
.x();
2555 event
->y
= unlocked_mouse_position_
.y();
2556 event
->windowX
= unlocked_mouse_position_
.x();
2557 event
->windowY
= unlocked_mouse_position_
.y();
2558 event
->globalX
= unlocked_global_mouse_position_
.x();
2559 event
->globalY
= unlocked_global_mouse_position_
.y();
2561 unlocked_mouse_position_
.SetPoint(event
->x
, event
->y
);
2562 unlocked_global_mouse_position_
.SetPoint(event
->globalX
, event
->globalY
);
2566 void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
2568 if (host_
->is_hidden() ||
2569 (cursor_visibility_state_in_renderer_
== VISIBLE
&& is_visible
) ||
2570 (cursor_visibility_state_in_renderer_
== NOT_VISIBLE
&& !is_visible
))
2573 cursor_visibility_state_in_renderer_
= is_visible
? VISIBLE
: NOT_VISIBLE
;
2574 host_
->SendCursorVisibilityState(is_visible
);
2577 void RenderWidgetHostViewAura::SetOverscrollControllerEnabled(bool enabled
) {
2579 overscroll_controller_
.reset();
2580 else if (!overscroll_controller_
)
2581 overscroll_controller_
.reset(new OverscrollController());
2584 void RenderWidgetHostViewAura::SnapToPhysicalPixelBoundary() {
2585 // The top left corner of our view in window coordinates might not land on a
2586 // device pixel boundary if we have a non-integer device scale. In that case,
2587 // to avoid the web contents area looking blurry we translate the web contents
2588 // in the +x, +y direction to land on the nearest pixel boundary. This may
2589 // cause the bottom and right edges to be clipped slightly, but that's ok.
2590 aura::Window
* snapped
= NULL
;
2591 // On desktop, use the root window. On alternative environment (ash),
2592 // use the toplevel window which must be already snapped.
2593 if (gfx::Screen::GetScreenFor(window_
) !=
2594 gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE
)) {
2595 snapped
= window_
->GetRootWindow();
2597 snapped
= window_
->GetToplevelWindow();
2599 if (snapped
&& snapped
!= window_
)
2600 ui::SnapLayerToPhysicalPixelBoundary(snapped
->layer(), window_
->layer());
2602 has_snapped_to_boundary_
= true;
2605 void RenderWidgetHostViewAura::OnShowContextMenu() {
2607 showing_context_menu_
= true;
2611 void RenderWidgetHostViewAura::SetSelectionControllerClientForTest(
2612 scoped_ptr
<TouchSelectionControllerClientAura
> client
) {
2613 selection_controller_client_
.swap(client
);
2614 CreateSelectionController();
2617 void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect
& rect
) {
2618 SnapToPhysicalPixelBoundary();
2619 // Don't recursively call SetBounds if this bounds update is the result of
2620 // a Window::SetBoundsInternal call.
2621 if (!in_bounds_changed_
)
2622 window_
->SetBounds(rect
);
2623 host_
->WasResized();
2624 delegated_frame_host_
->WasResized();
2626 // Create the legacy dummy window which corresponds to the bounds of the
2627 // webcontents. This will be passed as the container window for windowless
2629 // Plugins like Flash assume the container window which is returned via the
2630 // NPNVnetscapeWindow property corresponds to the bounds of the webpage.
2631 // This is not true in Aura where we have only HWND which is the main Aura
2632 // window. If we return this window to plugins like Flash then it causes the
2633 // coordinate translations done by these plugins to break.
2634 // Additonally the legacy dummy window is needed for accessibility and for
2635 // scrolling to work in legacy drivers for trackpoints/trackpads, etc.
2636 if (!legacy_window_destroyed_
&& GetNativeViewId()) {
2637 if (!legacy_render_widget_host_HWND_
) {
2638 legacy_render_widget_host_HWND_
= LegacyRenderWidgetHostHWND::Create(
2639 reinterpret_cast<HWND
>(GetNativeViewId()));
2641 if (legacy_render_widget_host_HWND_
) {
2642 legacy_render_widget_host_HWND_
->set_host(this);
2643 legacy_render_widget_host_HWND_
->SetBounds(
2644 window_
->GetBoundsInRootWindow());
2645 // There are cases where the parent window is created, made visible and
2646 // the associated RenderWidget is also visible before the
2647 // LegacyRenderWidgetHostHWND instace is created. Ensure that it is shown
2649 if (!host_
->is_hidden())
2650 legacy_render_widget_host_HWND_
->Show();
2655 UpdateMouseLockRegion();
2659 void RenderWidgetHostViewAura::SchedulePaintIfNotInClip(
2660 const gfx::Rect
& rect
,
2661 const gfx::Rect
& clip
) {
2662 if (!clip
.IsEmpty()) {
2663 gfx::Rect to_paint
= gfx::SubtractRects(rect
, clip
);
2664 if (!to_paint
.IsEmpty())
2665 window_
->SchedulePaintInRect(to_paint
);
2667 window_
->SchedulePaintInRect(rect
);
2671 bool RenderWidgetHostViewAura::ShouldMoveToCenter() {
2672 gfx::Rect rect
= window_
->bounds();
2673 rect
= ConvertRectToScreen(rect
);
2674 int border_x
= rect
.width() * kMouseLockBorderPercentage
/ 100;
2675 int border_y
= rect
.height() * kMouseLockBorderPercentage
/ 100;
2677 return global_mouse_position_
.x() < rect
.x() + border_x
||
2678 global_mouse_position_
.x() > rect
.right() - border_x
||
2679 global_mouse_position_
.y() < rect
.y() + border_y
||
2680 global_mouse_position_
.y() > rect
.bottom() - border_y
;
2683 void RenderWidgetHostViewAura::AddedToRootWindow() {
2684 window_
->GetHost()->AddObserver(this);
2685 UpdateScreenInfo(window_
);
2687 aura::client::CursorClient
* cursor_client
=
2688 aura::client::GetCursorClient(window_
->GetRootWindow());
2689 if (cursor_client
) {
2690 cursor_client
->AddObserver(this);
2691 NotifyRendererOfCursorVisibilityState(cursor_client
->IsCursorVisible());
2694 ui::InputMethod
* input_method
= GetInputMethod();
2696 input_method
->SetFocusedTextInputClient(this);
2700 // The parent may have changed here. Ensure that the legacy window is
2701 // reparented accordingly.
2702 if (legacy_render_widget_host_HWND_
)
2703 legacy_render_widget_host_HWND_
->UpdateParent(
2704 reinterpret_cast<HWND
>(GetNativeViewId()));
2707 delegated_frame_host_
->SetCompositor(window_
->GetHost()->compositor());
2708 if (window_
->GetHost()->compositor())
2709 begin_frame_observer_proxy_
.SetCompositor(window_
->GetHost()->compositor());
2712 void RenderWidgetHostViewAura::RemovingFromRootWindow() {
2713 aura::client::CursorClient
* cursor_client
=
2714 aura::client::GetCursorClient(window_
->GetRootWindow());
2716 cursor_client
->RemoveObserver(this);
2718 DetachFromInputMethod();
2720 window_
->GetHost()->RemoveObserver(this);
2721 delegated_frame_host_
->ResetCompositor();
2722 begin_frame_observer_proxy_
.ResetCompositor();
2725 // Update the legacy window's parent temporarily to the desktop window. It
2726 // will eventually get reparented to the right root.
2727 if (legacy_render_widget_host_HWND_
)
2728 legacy_render_widget_host_HWND_
->UpdateParent(::GetDesktopWindow());
2732 void RenderWidgetHostViewAura::DetachFromInputMethod() {
2733 ui::InputMethod
* input_method
= GetInputMethod();
2735 input_method
->DetachTextInputClient(this);
2738 void RenderWidgetHostViewAura::ForwardKeyboardEvent(
2739 const NativeWebKeyboardEvent
& event
) {
2740 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2741 ui::TextEditKeyBindingsDelegateAuraLinux
* keybinding_delegate
=
2742 ui::GetTextEditKeyBindingsDelegate();
2743 std::vector
<ui::TextEditCommandAuraLinux
> commands
;
2744 if (!event
.skip_in_browser
&&
2745 keybinding_delegate
&&
2747 keybinding_delegate
->MatchEvent(*event
.os_event
, &commands
)) {
2748 // Transform from ui/ types to content/ types.
2749 EditCommands edit_commands
;
2750 for (std::vector
<ui::TextEditCommandAuraLinux
>::const_iterator it
=
2751 commands
.begin(); it
!= commands
.end(); ++it
) {
2752 edit_commands
.push_back(EditCommand(it
->GetCommandString(),
2755 host_
->Send(new InputMsg_SetEditCommandsForNextKeyEvent(
2756 host_
->GetRoutingID(), edit_commands
));
2757 NativeWebKeyboardEvent
copy_event(event
);
2758 copy_event
.match_edit_command
= true;
2759 host_
->ForwardKeyboardEvent(copy_event
);
2764 host_
->ForwardKeyboardEvent(event
);
2767 void RenderWidgetHostViewAura::SelectionUpdated(bool is_editable
,
2768 bool is_empty_text_form_control
,
2769 const ui::SelectionBound
& start
,
2770 const ui::SelectionBound
& end
) {
2771 selection_controller_
->OnSelectionEditable(is_editable
);
2772 selection_controller_
->OnSelectionEmpty(is_empty_text_form_control
);
2773 selection_controller_
->OnSelectionBoundsChanged(start
, end
);
2776 void RenderWidgetHostViewAura::CreateSelectionController() {
2777 ui::TouchSelectionController::Config tsc_config
;
2778 tsc_config
.max_tap_duration
= base::TimeDelta::FromMilliseconds(
2779 ui::GestureConfiguration::GetInstance()->long_press_time_in_ms());
2780 tsc_config
.tap_slop
= ui::GestureConfiguration::GetInstance()
2781 ->max_touch_move_in_pixels_for_click();
2782 tsc_config
.show_on_tap_for_empty_editable
= true;
2783 tsc_config
.enable_longpress_drag_selection
= false;
2784 selection_controller_
.reset(new ui::TouchSelectionController(
2785 selection_controller_client_
.get(), tsc_config
));
2788 void RenderWidgetHostViewAura::HandleGestureForTouchSelection(
2789 ui::GestureEvent
* event
) {
2790 switch (event
->type()) {
2791 case ui::ET_GESTURE_LONG_PRESS
:
2792 if (selection_controller_
->WillHandleLongPressEvent(
2793 base::TimeTicks() + event
->time_stamp(), event
->location_f())) {
2794 event
->SetHandled();
2797 case ui::ET_GESTURE_TAP
:
2798 if (selection_controller_
->WillHandleTapEvent(event
->location_f()))
2799 event
->SetHandled();
2801 case ui::ET_GESTURE_SCROLL_BEGIN
:
2802 selection_controller_client_
->OnScrollStarted();
2804 case ui::ET_GESTURE_SCROLL_END
:
2805 selection_controller_client_
->OnScrollCompleted();
2812 ////////////////////////////////////////////////////////////////////////////////
2813 // DelegatedFrameHost, public:
2815 ui::Layer
* RenderWidgetHostViewAura::DelegatedFrameHostGetLayer() const {
2816 return window_
->layer();
2819 bool RenderWidgetHostViewAura::DelegatedFrameHostIsVisible() const {
2820 return !host_
->is_hidden();
2823 gfx::Size
RenderWidgetHostViewAura::DelegatedFrameHostDesiredSizeInDIP() const {
2824 return window_
->bounds().size();
2827 bool RenderWidgetHostViewAura::DelegatedFrameCanCreateResizeLock() const {
2828 #if !defined(OS_CHROMEOS)
2829 // On Windows and Linux, holding pointer moves will not help throttling
2831 // TODO(piman): on Windows we need to block (nested message loop?) the
2832 // WM_SIZE event. On Linux we need to throttle at the WM level using
2833 // _NET_WM_SYNC_REQUEST.
2836 if (host_
->auto_resize_enabled())
2842 scoped_ptr
<ResizeLock
>
2843 RenderWidgetHostViewAura::DelegatedFrameHostCreateResizeLock(
2844 bool defer_compositor_lock
) {
2845 gfx::Size desired_size
= window_
->bounds().size();
2846 return scoped_ptr
<ResizeLock
>(new CompositorResizeLock(
2849 defer_compositor_lock
,
2850 base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs
)));
2853 void RenderWidgetHostViewAura::DelegatedFrameHostResizeLockWasReleased() {
2854 host_
->WasResized();
2857 void RenderWidgetHostViewAura::DelegatedFrameHostSendCompositorSwapAck(
2858 int output_surface_id
,
2859 const cc::CompositorFrameAck
& ack
) {
2860 host_
->Send(new ViewMsg_SwapCompositorFrameAck(host_
->GetRoutingID(),
2861 output_surface_id
, ack
));
2864 void RenderWidgetHostViewAura::DelegatedFrameHostSendReclaimCompositorResources(
2865 int output_surface_id
,
2866 const cc::CompositorFrameAck
& ack
) {
2867 host_
->Send(new ViewMsg_ReclaimCompositorResources(host_
->GetRoutingID(),
2868 output_surface_id
, ack
));
2871 void RenderWidgetHostViewAura::DelegatedFrameHostOnLostCompositorResources() {
2872 host_
->ScheduleComposite();
2875 void RenderWidgetHostViewAura::DelegatedFrameHostUpdateVSyncParameters(
2876 const base::TimeTicks
& timebase
,
2877 const base::TimeDelta
& interval
) {
2878 host_
->UpdateVSyncParameters(timebase
, interval
);
2881 void RenderWidgetHostViewAura::OnDidNavigateMainFrameToNewPage() {
2882 ui::GestureRecognizer::Get()->CancelActiveTouches(window_
);
2885 uint32_t RenderWidgetHostViewAura::GetSurfaceIdNamespace() {
2886 return delegated_frame_host_
->GetSurfaceIdNamespace();
2889 ////////////////////////////////////////////////////////////////////////////////
2890 // RenderWidgetHostViewBase, public:
2893 void RenderWidgetHostViewBase::GetDefaultScreenInfo(WebScreenInfo
* results
) {
2894 GetScreenInfoForWindow(results
, NULL
);
2897 } // namespace content